Skip to content

Add Game "Fox and Geese" - #1583

Open
Stochastic-Batman wants to merge 6 commits into
google-deepmind:masterfrom
Stochastic-Batman:fox_and_geese
Open

Add Game "Fox and Geese"#1583
Stochastic-Batman wants to merge 6 commits into
google-deepmind:masterfrom
Stochastic-Batman:fox_and_geese

Conversation

@Stochastic-Batman

Copy link
Copy Markdown

Implements Fox and Geese, an asymmetric, zero-sum, perfect-information hunting game played on a 33-point cross-shaped board (7x7 grid with the four 2x2 corners removed). One fox tries to capture geese by jumping over them; the geese try to trap the fox so it has no legal move. The fox wins if it reduces the geese below the number needed to trap it (4); the geese win by immobilizing the fox; a player with no legal move loses; games reaching the move limit are declared a draw.

Here's the starting position (13 geese, the traditional default):

image

Only the classic one-fox game is implemented, with the three traditional starting configurations (13/15/17 geese, selectable via the num_geese parameter). The two-fox Scandinavian variant (Halatafl/Rävspelet) and Asalto are out of scope - they have different win conditions and board rules, and are separate games rather than parameterizations of this one.

Captures are optional and may be chained (a jump keeps the turn if a further jump is available); geese in the 15/17-goose configurations are restricted to forward/sideways movement, per the historical rules that offset the extra material.

Closes #1581.

Testing

  • Full test suite passes: 293/293, including fox_and_geese_test, pyspiel_test.py, and api_test.py.
  • fox_and_geese_test.cc covers all three starting layouts, board geometry (diagonal vs. orthogonal points), optional and chained captures, goose movement restrictions, both win conditions, undo, and JSON struct round-trips (including mid-jump-chain states), plus RandomSimTest/RandomSimTestWithUndo across all configurations.
  • Invalid num_foxes/num_geese values are rejected at construction with explanatory errors; verified via pyspiel.load_game.
  • Verified interactively via example and mcts_example, including 1000-simulation MCTS self-play across all three configurations, which exercised multi-jump chains (up to 5 captures in a single turn) end to end.
  • Playthrough file generated and passing via playthrough_test.py.

Adds the initial file structure, header declarations, and build setup for
the Fox and Geese game.

- Created `fox_and_geese.h` with state space calculations (that I posted on Mathematics Stack Exchange: https://math.stackexchange.com/questions/5145511/fox-and-geese-state-space-calculation) and game parameters
- Added `fox_and_geese` library target to `CMakeLists.txt`
- Registered new game in Python bindings test suite
Replace the copied tic-tac-toe initialization with Fox and Geese setup:

- Add a compile-time mask for the 33-point cross (7x7 grid minus the four
  2x2 corners) and use it to mark out-of-bounds cells.
- Add the nested traditional geese layout table, read as a prefix of
  length num_geese, with the fox on the center point.
- Wire up the num_foxes/num_geese parameters and reject anything other
  than one fox and 13, 15, or 17 geese.
- Fix the cell state helpers for the fox/goose/out-of-bounds enum.
- Drop the tic-tac-toe line-win logic and IsFull(); IsTerminal() now
  reads outcome_ only.

Move generation, win conditions, undo, and the struct-based constructor
are still stubbed and do not compile yet.
Replace the placeholder placement logic with the real rules.

- Add compile-time adjacency and jump tables. Diagonals exist only on
  lines incident to the five hub points, and are recorded in both
  directions; jumps are derived edge by edge rather than assumed, so
  hub-to-hub lines like (3,1)-(2,2)-(1,3) are included and off-board
  ones like (3,3)-(2,2)-(1,1) are not.
- Encode actions as (from, to) pairs plus a reserved end-turn action,
  and update NumDistinctActions and the action struct to match.
- Generate fox steps and jumps, and geese steps restricted to forward
  and sideways in the 15- and 17-goose games.
- Keep the move with the fox while further jumps are available, since
  captures are optional and may be chained.
- Set the outcome when the geese fall below kMinGeeseToTrapFox or the
  player to move has no legal action, and draw at the move limit.
- Reverse moves, captures, and chain state via an undo record stack.
- Rebuild the struct-based constructor around the board shape and the
  real piece counts.
- Add the games.md entry.
- Start with the geese to move, per the majority of rule sets.
- Carry continue_jump_from through the state struct so a fox partway
  through a jump chain survives serialization, and reject values that
  no reachable state could produce.
- Serialize the stored current player rather than CurrentPlayer(),
  which reports kTerminalPlayerId and so made terminal states fail to
  round-trip.
- Document that a player with no legal move loses and that reaching
  the move limit is a draw.
Add fox_and_geese_test.cc covering:

- game parameters and the num_foxes/num_geese validators
- all three starting layouts (13/15/17 geese) against expected board
  strings, piece counts, and opening move counts
- board geometry (diagonal vs non-diagonal points) via legal-move counts
  from isolated positions
- optional captures and multi-jump chains, including kEndTurnAction
- goose movement restrictions in the 15/17-goose games
- both win conditions and the no-legal-move rule
- UndoAction for steps and captures
- state/observation/action struct JSON round-trips, including a
  mid-jump-chain state
- RandomSimTest and RandomSimTestWithUndo across all three configs
@google-cla

google-cla Bot commented Jul 31, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@lanctot

lanctot commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add game "Fox and Geese"

2 participants