ritchie/elements/wall
The wall of tiles (牌山/山/壁牌) and utils.
How we represent the wall
_______________ ______________
<--- TAIL (CCW) | / HEAD (CW) --->
self draws | dora indicators |rinshan| | initial deal | self draws
118 120|122 124 126 128 130|132 134| | 0 2 4 6 8 10 48 50 |52 54
... +---+---*---+---+---+---+###*---+---+ +---+---+---+---+---+---+ ... +---+---*---+---+ ...
|#66|#68| D4| D3| D2| D1| D0|RS2|RS0| |E0 |E2 |S0 |S2 |W0 |W2 | |E12|W12|#00|#02| TOP
... +===+===*===+===+===+===+===*===+===+ +===+===+===+===+===+===+ ... +===+===*===+===+ ...
|#67|#69|UD4|UD3|UD2|UD1|UD0|RS3|RS1| |E1 |E3 |S1 |S3 |W1 |W3 | |S12|N12|#01|#03| BOTTOM
... +---+---*---+---+---+---+---*---+---+ +---+---+---+---+---+---+ ... +---+---*---+---+ ...
119 121|123 125 127 129 131|133 135| | 1 3 5 7 9 11 49 51 |53 55
self draws |ura-dora indicators|rinshan| | initial deal | self draws
In a physical game, the following procedure is used to prepare the wall:
-
Shuffle: 136 tiles => 4 sides x 17 stacks x 2 tiles per stack, treated as a ring.
-
Randomly decide the splitting point on this ring (rules vary on this).
-
From the splitting point: clockwise => head, counterclockwise => tail. Now the ring can be treated as a linear 68 x 2 array of tiles.
-
Reveal the top tile of the 3rd stack from tail; this is the first Dora Indicator. (figure:
###) -
Initial deal: Players take turns (E->S->W->N->E->…) to draw 2 stacks (= 4 tiles) from the head until everyone has 12. Each player then draws one more tile. (figure:
E0E3,S0S3, (…),W8W11,N8N11;E12,S12,W12,N12) -
The button player takes his first self-draw and the round starts. (figure:
#00) -
Additional draw after each Kan is taken from the tail. (figure:
RS0,RS1,RS2,RS3) -
Additional Dora Indicators are flipped further from tail since the initial one. (figure:
D1,D2,D3,D4)
In this library, we assign an index to each of the 136 tiles in the “linear” wall after splitting. The split wall is indexed head-to-tail (major), top-to-bottom (minor). In the figure, this index is annotated as numbers next to the boxes (above/below).
Ref
Types
Wall with some tiles unknown.
pub opaque type PartialWall
Values
pub fn deal(
wall: Wall,
button: player.Player,
) -> List(tile_set37.TileSet37)
Draws the initial 13 tiles for each of the 4 players, according to standard rules.
pub const deal_index: List(List(Int))
For each player starting from the bottom player, which wall tiles to take as the initial draw?
pub const dora_indicator_index: List(Int)
Indices of dora indicators in the wall, by their order of revealing
pub fn dora_indicators(wall: Wall) -> List(tile.Tile)
Returns the entire dora indicator section of the wall as a list. This does not handle gradual revealing of dora indicators.
pub fn fill_missing_tiles_in_partial_wall(
pwall: PartialWall,
missing_tiles: List(tile.Tile),
) -> Wall
Combine the partially-known wall and (reordered) unknown tiles to form a fully known wall. Panics when not enough tiles are present to fill the “holes” in the partial wall. Doesn’t check the validity of the resulting wall.
pub fn get_missing_tiles_in_partial_wall(
pwall: PartialWall,
num_reds: #(Int, Int, Int),
) -> tile_set37.TileSet37
Deduces the set of unknown tiles from the given partially-known wall, and the known total number of red tiles. Panics when the partially-known wall is inconsistent with the assumed complete set of tiles.
pub fn is_valid_wall(wall: Wall) -> Bool
Makes sure that a wall is valid, meaning 34 kinds x 4 each = 136
pub const kan_draw_index: List(Int)
Indices of kan draws in the wall, first to last
pub fn make_dummy_wall() -> Wall
Constructor for an obviously invalid wall. Useful for mutating later.
pub fn make_sorted_wall(num_reds: #(Int, Int, Int)) -> Wall
pub fn ura_dora_indicator(wall: Wall, i: Int) -> tile.Tile
Returns the indexed (0..=4) ura-dora indicator.
pub const ura_dora_indicator_index: List(Int)
Indices of ura-dora indicators in the wall, by their order of revealing