Bloom

Grow your colour, starve theirs. One tap a turn.

▶ 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

# 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

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

 1"""Bloom: Grow your colour, starve theirs. One tap a turn.
 2
 3# /// simvx
 4# tags = ["game", "strategy", "hex", "2d", "ai", "touch"]
 5# screenshot_frame = 90
 6# web = { width = 900, height = 700, root = "BloomApp", responsive = true }
 7# ///
 8
 9An original abstract hex-territory game. Tap one empty hex to drop a seed of
10your colour; every adjacent enemy hex your placement now outnumbers flips to
11you, and the flips cascade outward in a visible wave. When the board fills, the
12majority wins.
13
14Capture is local: a hex flips when the seeds touching it are outnumbered, so the
15same rule lets you take enemy cells and lose your own exposed ones. Keep your
16shapes connected.
17
18Modes: vs Computer (Calm / Sharp / Ruthless) or two-player hotseat.
19Controls: press/hold an empty hex to preview which cells flip, release to place.
20Esc = menu, Z = undo, H = help, R = restart. Plays identically with a mouse or a
21single finger on a touchscreen.
22"""
23
24from app import BloomApp  # noqa: F401  (re-exported for the web exporter)
25
26from simvx.graphics import App
27
28
29def main() -> None:
30    App(title="Bloom", width=900, height=700).run(BloomApp())
31
32
33if __name__ == "__main__":
34    main()