Skip to main content

AI CoC

PyPI version python uv Ruff ty Pydantic v2 tests code-quality Ask DeepWiki license PRs contributors

A Windows desktop application that plays Clash of Clans for you inside MuMu Player 12. It reads the screen itself and turns what it finds into ADB taps, checking the outcome on the next screenshot. Gemini is asked exactly one question per battle: how to attack this village.

Other Languages: English | 繁體中文 | 简体中文

✨ What it does

Attacks for loot on its own. It searches for opponents, skips the ones carrying less than your thresholds, puts the whole army down in about ten seconds and plays the battle out, then comes round for the next one. It stops by itself when the storages are full. Screen reading is done here rather than sent away: the loot panel, the army bar and every card in the row are matched against templates, so a skipped opponent costs nothing and a battle is never waiting on a network call.

Asks Gemini exactly one question per battle, and only after an opponent has already passed your thresholds: how to attack this particular village. It answers where to drop the line of troops, where each rage and freeze goes, and which hero is on which card. Without an API key the app plays a fixed tactic instead and everything else still works.

Spends what it farms. Wall upgrades finish the moment they are paid for, so they are where a full storage goes; the loop finds walls on the map, works out the cheapest batch the village can afford and buys it. Idle builders can be put on the most expensive upgrade affordable, and heroes raised one at a time.

Keeps the village ticking. Empties the collectors, reads what every builder is on and how long is left, and donates troops to whoever is asking in the clan chat.

Recovers on its own. A session dropped for idling restarts the game and carries on, whichever loop was running. Every command typed into the AI tab is stored as a task, so an interrupted run is picked up again on the next start.

Keeps your key out of plain settings. The Gemini API key is stored through Windows DPAPI, never in the registry or a config file.

Imported village exports keep unknown fields and unknown data_ids instead of failing on them, and imported battle scripts are not played back: they are validated for army requirements and stop at a reserved handoff boundary.

📋 Requirements

  • Windows. The app talks to mumu-cli.exe, reads the registry through winreg and calls DPAPI through ctypes.windll, none of which exist elsewhere
  • MuMu Player 12 with Clash of Clans installed, running at 1600x900
  • A Gemini API key. The per-battle tactic and the whole AI tab need it; enter it in the app's settings tab. Without one the attack loop falls back to a fixed tactic, and the wall, collector, builder, hero and donation commands never ask it anything in the first place

🚀 Install and run

From PyPI, without installing anything permanently:

uvx ai_coc

Or as a regular install:

uv tool install ai_coc
ai_coc

Prebuilt Windows executables are attached to every release.

🎮 Playing from the terminal

The window is one way in. The other is a sub-command, which runs the same loops with no window at all, and this is how the game is usually played, because it leaves the terminal free to watch the log.

Attacking

ai_coc attack                    # one battle
ai_coc attack --repeat 5         # five in a row
ai_coc attack --repeat 0         # keep going until a storage fills up
ai_coc stop                      # stand down after the battle in progress
ai_coc attack --restart-every 0  # skip the scheduled emulator restart this run
ai_coc attack --stop-at 0        # attack however full the storages are

The emulator is restarted every so many battles, because MuMu drops frames after running for a while and nothing short of a restart clears it. How many sits in the settings file (restart_every, 50 by default) rather than being hard-coded, because that number is whatever a given machine turns out to need — --restart-every overrides it for one run, and 0 there turns it off the same way the loot flags do. It counts battles rather than rounds, so a night mostly spent waiting on the barracks does not spend restarts on an emulator that has barely been working.

stop writes a flag and returns at once. The loop reads it between battles and between opponents, never mid-battle, so the worst case is one more battle: abandoning one halfway would leave the army on the field and the game on a screen the next run cannot get home from.

Loot thresholds come from the settings file, and can be overridden for one run. Passing 0 is different from leaving a flag out: out means "use the configured value", 0 means "take this threshold out entirely":

ai_coc attack --min-gold 800000
ai_coc attack --min-gold 0 --min-elixir 0 --min-dark 0    # attack whoever comes up first

A run can keep everything it looked at, which is what makes a battle worth arguing with afterwards:

ai_coc attack --record                # every frame the loop reads, named for what it was asking
ai_coc attack --record --shot-every 4 # plus one frame every four seconds

A tactic is a file rather than a set of constants, so a battle worth repeating can be repeated and one worth arguing with can be edited. Replaying one calls Gemini not at all:

ai_coc attack --plan-out used.json    # write down whichever plan actually ran
ai_coc attack --plan-in used.json     # play that one again, edits included

Spending what you farmed

ai_coc walls                          # buy wall upgrades until the storages will not stretch
ai_coc walls --keep-elixir 2000000    # leave that much behind to train an army with
ai_coc upgrade                        # put idle builders on the dearest upgrade affordable
ai_coc hero                           # what raising each hero next would cost
ai_coc hero --upgrade duke            # put a builder on that one

A wall upgrade needs a free builder and hands it straight back, so walls stops and says so when every builder is busy. hero reads by default and only spends when told which hero, because which one is worth a builder is a judgement about how the village plays.

Keeping the village going

ai_coc collect                        # empty every collector that has something waiting
ai_coc builders                       # what each builder is on, and how long is left
ai_coc donate                         # give troops to whoever in the clan is asking
ai_coc donate --dry-run               # walk the whole path and stop before giving anything

Getting the game up

Every other command assumes the game is already running and brings it up if it simply is not. What it cannot fix is an emulator or a game that is up and no longer answering, which is what these are for:

ai_coc launch                         # start the emulator if it is down, bring the game up
ai_coc launch --restart game          # relaunch the game, leave the emulator alone
ai_coc launch --restart emulator      # restart the emulator, then bring the game up again

Looking at what it sees

ai_coc capture ./shots --count 30     # a burst off the live game
ai_coc read shot.png                  # what each reader makes of one frame
ai_coc view --zoom out                # put the camera back where every coordinate was measured
ai_coc world                          # which of the two villages the game is on
ai_coc world --go day                 # sail there; already being there does nothing
ai_coc attack --world night           # attack the builder base instead of the home village

The game keeps two villages — the home village and the builder base — and reopens on whichever one it was closed on, so world is worth asking before anything that assumes one of them. Reading it is a single screenshot: no tap, no swipe, no camera move.

read is the quickest way to answer "did it misread the screen, or did the tap miss?" It prints what every reader got from one frame: the loot panel, the storages, the card row and the builder panel.

Where a run leaves what it saw

Every run gets a directory of its own, whichever side of the app started it:

~/.ai_coc/logs/2026-08-29-011423-attack/
├── run.log        # this run's log, and nothing else
├── result.json    # what the command answered
├── plans.jsonl    # ai_coc attack only: one line per round, the tactic it played
└── frames/        # only with --record

The first line of every run says which directory it is, and the name is <when>-<what> so a listing reads as a history. There is no second file mixing every run together — grep -r ~/.ai_coc/logs/*/run.log answers across runs and tells you which one each hit came from.

⚙️ Settings

~/.ai_coc/config.json is read by both the window and the terminal, so a run plays the same way from either side:

{
  "thresholds": {
    "min_gold": 500000,
    "min_elixir": 500000,
    "min_dark": 5000
  },
  "stop_at": 90
}
  • thresholds: who is worth attacking. Set them too high and a run skips dozens of opponents without ever starting a battle
  • stop_at: how full every storage has to be before a run stands down, as a percentage. One number for both villages, because the loop reads each storage's real ceiling off the game — tap a storage bar and it writes 最大儲存量 on the spot. Every storage has to reach it, not just one of them: a battle brings home three, so one at the ceiling is no reason to stop earning the other two. 0 never stands a run down, and a storage whose ceiling would not read is left out of the count. --stop-at overrides it for one run, 0 included, which is what a test battle against a village that farming has just filled needs

There are no ability or spell timings here any more. They were a table of per-hero constants, and editing them meant guessing how long an army takes to walk across a village nobody had looked at — which is the planner's job, done with the village on screen. Every clock lives on the plan now: see plans/flat.json for the shape, and --plan-in to replay one.

Everything else lives in ~/.ai_coc: the SQLite database, captured frames, imported account JSON, the log, and the DPAPI-protected key file.

🤝 Contributing

Setup, architecture, packaging and the CI layout live in CONTRIBUTING.md.

📄 License

MIT, see LICENSE.

Metadata

Release files for ai_coc 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ai_coc 0.5.1
File Size Uploaded
ai_coc-0.5.1.tar.gz 418.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for ai_coc 0.5.1
File Interpreter ABI Platform
ai_coc-0.5.1-py3-none-any.whl Python 3 none any Details

Total release size: 671.5 kB

Release files / ai_coc-0.5.1.tar.gz

Download URL ai_coc-0.5.1.tar.gz
Size 418.4 kB
Tags Source
SHA-256 checksum
How to use checksums
55864d2f4bd77ff5e3d0f34411992c78fa6c6150f5603fd16ceda015c97c2de8
BLAKE2b-256 checksum
How to use checksums
6dffc3244e28ad4b4075f209e8670ad6f0b148cd77bc51f5d6d7b2374ab21dad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / ai_coc-0.5.1-py3-none-any.whl

Download URL ai_coc-0.5.1-py3-none-any.whl
Size 253.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
78ed142d9e7e8d999e5a9adf5d200c72e6ed2820f5471d6c4c37f7f8de1368e1
BLAKE2b-256 checksum
How to use checksums
51c461133690eb69d00ec66d613b2fd213bc9f822417a0dadfd5ca26179ed0fd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page