README.md

This commit is contained in:
2025-09-09 08:24:02 -06:00
parent 5f70243041
commit 516bdbe213

View File

@@ -10,16 +10,7 @@ build/candyland
```text
games played: 1000000
player 0 won: 274882
player 1 won: 257248
player 2 won: 240726
player 3 won: 227144
total draws: 31659948
backwards moves: 940653
shortcuts taken: 1277005
didn't move: 18
empty BoW: 3576
landed on another: 2966229
longest game: 81 draws
shortest game: 6 draws
0: 0
@@ -120,4 +111,68 @@ Here's ours, featuring two shortcuts and a split path:
![](board.jpg)
The simulation code has two interesting points of complexity:
### Handling the Split Path
The 83 board spaces are laid out in a 1D array.
It's appealing to just search forward from the player position to find the next space of the appropriate color, however, the forked path means this will occasionally produce an invalid move.
If the left branch (blue/green/purple) is stored before the right branch (yellow/orange/red), and a player on the left branch draws a red card, this would cause them to jump over to a space on the right branch.
To avoid this, each space also stores 1 or 2 following spaces: the forking space has two, and all other spaces have one.
Before a piece can be moved, this simple graph of spaces needs to be traversed to actually determine the pool of reachable spaces.
### Disallowing Shared Occupancy
The second source of complexity is disallowing two pieces from sharing a space on the board.
The basic logic is wrapped up in a function like this:
* Inputs: starting location, target color
* Output: ending location
* Examine all reachable spaces starting from the start location
* If the space is the target color, return its index unless it's already occupied.
In the case of landing on a shortcut, it takes sadvantage of the fact that both shortcuts on this board jump the player to the next space of the same color.
We just restart this logic from the shortcut start location with the same target color.
In the case of a candy card, we scan the whole board to look up the target space (since it might be behind the starting location).
Then, apply the move logic starting from immediately before the target space, targeting the next pink space.
This handles the case where the target space is occupied by a player, and needs to be skipped to land on the next pink space.
## Results
I ran 1,000,000 simulations
| Player Won | % Observed (raw) |
|-|-|
| 1 | 27.5% (274882) |
| 2 | 25.7% (257248) |
| 3 | 24.1% (240726) |
| 4 | 22.7% (227144) |
Going first (i.e., being the youngest player) confers a 1.8pp advantage relative to the closest competition.
If you go last, you can expect to win only 22.7% of games.
Other statistics over 1M games:
| Stat | Value |
|-|-|
| Cards drawn | 31,659,948 |
| Backwards Moves | 940,653 (2.97% of draws) |
| Shortcuts Taken | 1,277,005 (4.03% of draws) |
| Didn't move | 18 |
| Empty Bag of Wonders | 3,576 |
| Landed on Another Player | 2,966,229 |
The longest observed game was 81 draws, and the shortest was 6.
![](histo.png)
The six turn game goes like this, and requires player 1 to do certain moves first.
1. Player 1 goes to ice cream
2. Player 2 goes to mint
3. ...
4. ...
5. Player 1 draws double red: first one takes him across the shortcut, second takes him to the red ahead of player 2.
6. Player 2 draws double red: lands on player 1 to skip to next red, second red takes him to the end.