Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

calcitem/Sanmill

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7,454 Commits
7,454 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Overview

Graphic

Get it on GitHub Get it on Google Play Get it on F-Droid
Download on the App Store Get it from the Microsoft Store Get it from the Snap Store Get it on CafeBazaar

snapcraft

Codemagic build status

Translation status

Readme-Chinese

Sanmill is a free, powerful N men's morris game with a Flutter GUI and a native Rust AI engine. It is distributed under the GNU Affero General Public License version 3 (AGPL v3), ensuring that it remains free software. Users can modify and redistribute the software, provided they adhere to the AGPL terms.

Nine men's morris is a strategy board game for two players dating back to the Roman Empire. The game is also known as nine-man morris, mill, mills, the mill game, merels, merrills, merelles, marelles, morelles, and ninepenny marl in English.

image

Files

This distribution of Sanmill consists of the following files:

  • Readme.md: The file you are currently reading.
  • Copying.txt: A text file containing the GNU Affero General Public License version 3.
  • crates: The Rust/TGF workspace containing the rules engine, search code, FRB API crate, and headless CLI.
  • src/ui/flutter_app: The Flutter frontend.
  • scripts: Build, test, and repository maintenance scripts.

Frontend Options

Sanmill's supported frontend is the Flutter app. Debugging and headless engine work use the Rust CLI in crates/tgf-cli.

How to Build

Console Engine

bash scripts/build_console_engine.sh

When reporting an issue or a bug, please provide information about the version and compiler used to create your executable. You can obtain this information by running:

target/release/tgf compiler

Flutter App

To build the Flutter app, run ./flutter-init.sh, and then use Android Studio or Visual Studio Code to open src/ui/flutter_app. The script automatically provisions Flutter 3.44.6 in .tools/flutter when the required SDK isn't already available on your system, ensuring the repository always uses the expected version.

We use compile-time environment configs to enable specific parts of the code:

  • test to prepare the app for Monkey and Appium testing. (References to external sites will be disabled.)
  • dev_mode to show the developer mode without needing to enable it first.
  • catcher to control the use of Catcher. (Enabled by default; disable if necessary.)

All environment configs can be combined and take boolean values, like:

flutter run --dart-define catcher=false dev_mode=true

Launch configurations for Android Studio or Visual Studio Code are available. Select the needed one in the Run and Debug or Run/Debug Configurations tab.

Rust / TGF Engine Workspace

Sanmill is being migrated toward TGF (TabletopGameFramework), a Rust + FRB framework shared by Mill and future tabletop games. The Rust workspace lives under crates/:

cargo test --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings

Mill rules and search are fully implemented in Rust (crates/tgf-mill, crates/tgf-search). The AI uses PVS with aspiration windows, null-move pruning, MTD(f), MCTS, and iterative deepening. The perfect database is kept as a vendored C++ library behind the Rust perfect-db wrapper.

The Flutter bridge is generated by flutter_rust_bridge (FRB). ./flutter-init.sh will build the Rust workspace and run FRB code generation when cargo and flutter_rust_bridge_codegen are available. You can also run code generation manually:

cd src/ui/flutter_app
flutter_rust_bridge_codegen generate

Rust performance smoke results use the same TOML schema as tests/perf_baseline.toml:

python scripts/record_rust_perf_baseline.py --output target/tgf_perf_result.toml
python scripts/check_perf_baseline.py   --baseline tests/perf_baseline.toml   --result target/tgf_perf_result.toml

For fixed-depth search optimization A/B measurements, including node-count parity requirements, see docs/FRAMEWORK_API.md.

For the framework API contract, see docs/FRAMEWORK_API.md.

Understanding the Code Base and Participating in the Project

Sanmill's improvements have been a community effort. You can contribute in several ways:

Improving the Code

  • Sanmill Wiki: Contains explanations of techniques used in Sanmill, with background information.
  • GitHub Repository: The latest source can always be found here.
  • Discussions: Join discussions about Sanmill.

Terms of Use

Sanmill is distributed under the GNU Affero General Public License version 3 (AGPL v3). This allows you to use, modify, and distribute the software, provided you include the full source code or a pointer to where the source can be found. Any changes to the source code must also be made available under the AGPL.

For full details, see the AGPL v3 in the Copying.txt file.

Note on App Store Distribution: As an additional permission under section 7 of the AGPL v3, you are allowed to distribute the software through app stores, even if they have restrictive terms that are incompatible with the AGPL. However, the source code must also be available under the AGPL, either through the app store or another channel without those restrictive terms.

All unofficial builds and forks of the app must be clearly labeled as unofficial (e.g., "Sanmill UNOFFICIAL") or use a different name altogether. They must use a different application ID to avoid conflicts with official releases.

Crash Reporting and Privacy

Sanmill collects non-sensitive crash information to help improve the software. The information collected may include:

  • Device type and operating system version
  • The actions leading up to the crash
  • The crash error message

Users can review the crash report contents before sending. No personally identifiable information (PII) is collected, and all data is anonymized to ensure user privacy. Users can choose not to send crash reports if they prefer.

This data is used solely for improving the quality and stability of Sanmill and is not shared with any third parties.

Free Software Philosophy

Sanmill is free software, and we emphasize the importance of free software as a matter of freedom. We encourage the use of AGPL v3 or later as a license for contributions and discourage the use of non-free licenses.

Optional AI Game Analysis

AI Game Analysis is an optional, 18+ feature that is disabled by default and restricted to fixed game-analysis tasks. It is not a person, may be inaccurate, and is not professional advice. Sanmill does not provide a hosted inference service. Desktop users may use a loopback-only Ollama installation with the mandatory gpt-oss-safeguard:20b classifier, or users may choose an HTTPS proxy whose operator and privacy policy are shown before consent.

Each analysis request contains only the selected task, app language, game variant and rules, FEN position, side and phase, piece counts, and bounded move notations. It excludes player names, comments, device identifiers, clipboard contents, and arbitrary chat text. Proxy credentials use platform secure storage; browser credentials are session-only. Changing the endpoint, model, operator, privacy URL, protocol, or consent notice requires fresh consent.

AI-answer reports are submitted in-app. Reports contain metadata only unless the user checks an unchecked option and reviews or redacts the answer. The EU D1 relay stores raw reports for 30 days, keeps de-identified category totals for 12 months, never stores raw IP addresses, and issues a deletion token.

Official releases must keep SANMILL_ENABLE_AI_ANALYSIS=false unless all of the following are complete: deploy both reference Workers; create the report D1 database with wrangler d1 create sanmill-ai-reports-eu --jurisdiction=eu; configure Worker secrets and disable body logs; complete provider DPA/transfer safeguards; obtain counsel review of the EU AI Act/GDPR notice and Article 27 representative assessment; update Apple and Google privacy/data-safety and AI content declarations; and verify in-app reporting and deletion. After approval, build with both --dart-define=SANMILL_ENABLE_AI_ANALYSIS=true and an HTTPS --dart-define=SANMILL_AI_REPORT_RELAY_URL=... value. The compile-time gate fails closed when either value is missing.

For the inference proxy, set OPENAI_API_KEY as a Worker secret and optionally set ACCESS_TOKEN; do not place either in wrangler.jsonc. For the report relay, replace the D1 database ID, apply migrations/0001_reports.sql, and set RATE_LIMIT_SECRET as a Worker secret. Run pnpm run typecheck and pnpm test in each service directory before deployment. Cloudflare's --jurisdiction=eu constraint, rather than a Western Europe location hint, is required because only the jurisdiction setting guarantees that D1 runs and stores data within the EU.

About

Sanmill is an open-source, UCI-like Mill/Morris/Merrills/Mühle/Malom (and its variants) program with CUI, Flutter GUI and Qt GUI, sharing and freely distributing the code, tools and data needed to deliver this mill game. We do this because we are convinced that open software and open data are key ingredients to make rapid progress.

Topics

Resources

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.