# Bloom Grow your colour, starve theirs. One tap a turn. ```{raw} html ▶ Run in browser ``` **Tags:** `game` `strategy` `hex` `2d` `ai` `touch` # Bloom **Grow your colour, starve theirs. One tap a turn.** Bloom is an original abstract hex-territory game built on SimVX. The whole game is one rule and one gesture: tap an empty hex to drop a seed of your colour; every adjacent enemy hex your placement now *outnumbers* flips to you, and the flips cascade outward in a visible wave. When the 61-cell board fills, the majority wins. Matches last a couple of minutes and play identically with a mouse or a single finger on a phone. ## The one rule - The board is a hexagon of 61 cells. It opens with one amber and one azure seed on opposite rims; the centre starts empty. - On your turn, press an empty cell to aim (a preview rings the cells that would flip) and release to place a seed of your colour. Sliding off the board before releasing cancels. - **Capture is local, not about totals.** A hex is judged only by the cells *touching* it: an enemy hex flips when your seeds touching it **strictly outnumber** its own colour touching it. Captures cascade: a freshly flipped cell can tip its neighbour over, rippling outward ring by ring. - The rule is symmetric, so **your** hexes flip the same way on the opponent's turn. A big connected group is safe in its interior (each cell is touched by many friends), but a thin, exposed cell can be flipped by two adjacent enemies even if they own very few cells overall. Keep your shapes connected. - Ties never capture and empty cells count for neither side, so rim and corner cells (fewer neighbours) are naturally defensible while the open centre is the most volatile. - The board has an odd number of cells, so a draw is impossible. Strict majority wins. ## Modes - **vs Computer** with three difficulties: **Calm** (greedy), **Sharp** (looks one move ahead), **Ruthless** (depth-2 search). The AI is fair: it plays the same legal moves through the same capture rule you do, with no hidden state. - **2 Players** hotseat on one device. ## Controls | Action | Desktop | Touch | | --- | --- | --- | | Place a seed | Press an empty hex (preview), release to place | Hold an empty hex (preview), lift to place | | Menu | `Esc` | **Menu** button | | Undo | `Z` / `Backspace` | **Undo** button | | Help | `H` | **Help** button | | Restart | `R` | Rematch on the game-over card | Everything is reachable by touch: large hit targets, a bottom control strip, and no hover-only information. The layout is anchored and re-fits the board to the viewport, so it works on desktop, phone landscape and phone portrait. ## Run it ```bash # Desktop uv run python examples/demos/bloom/main.py # In a browser (Vulkan-rendered frames streamed over WebSocket) uv run python examples/demos/bloom/web.py # then open http://localhost:8080 ``` ## Architecture Pure game logic is kept completely separate from rendering, input and UI, so the rules and AI are deterministic and unit-testable with plain pytest. | File | Responsibility | | --- | --- | | `hex_grid.py` | Pointy-top axial hex math, parametrized by viewport size. | | `board.py` | `Owner`, `Board`, and `resolve_placement` (the capture cascade). Pure. | | `ai.py` | Negamax + alpha-beta over board copies. Pure. | | `render.py` | `HexBoardView`: fit, hit-test and draw the board via `Draw2D`. | | `game.py` | `BloomGame` node: turns, animation, AI pacing, undo, HUD, signals. | | `menu.py` | `MainMenu` and the live `HowToCard`. | | `app.py` | `BloomApp` root: screen state machine, global input, bottom bar. | | `main.py` / `web.py` | Desktop and browser-streaming entry points. | The capture resolver is the single source of truth: the player turn, the cascade animation, and the AI search all run the exact same function. ## Tests ```bash uv run --package simvx-core pytest examples/demos/bloom/tests ``` `test_board.py` pins the rules (capture, cascade, ties, edge defensibility, no-draw parity, determinism), `test_ai.py` checks legality, determinism and that deeper search plays stronger, and `test_game_flow.py` drives the game node with simulated input through `SceneRunner` and verifies signals, undo and game-over. ## Why it is original Bloom is its own game with its own theme, rules and balance. Game mechanics are not copyrightable, and none of this code is copied from any other game. The hex coordinate math follows the standard, public cube/axial formulation. ## Source ```{literalinclude} ../../examples/demos/bloom/main.py :language: python :linenos: ```