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:

  1. Shuffle: 136 tiles => 4 sides x 17 stacks x 2 tiles per stack, treated as a ring.

  2. Randomly decide the splitting point on this ring (rules vary on this).

  3. From the splitting point: clockwise => head, counterclockwise => tail. Now the ring can be treated as a linear 68 x 2 array of tiles.

  4. Reveal the top tile of the 3rd stack from tail; this is the first Dora Indicator. (figure: ###)

  5. 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)

  6. The button player takes his first self-draw and the round starts. (figure: #00)

  7. Additional draw after each Kan is taken from the tail. (figure: RS0, RS1, RS2, RS3)

  8. 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

The wall of tiles.

pub opaque type Wall

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 fn dora_indicator(wall: Wall, i: Int) -> tile.Tile

Returns the indexed (0..=4) dora indicator.

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 fn kan_draw(wall: Wall, i: Int) -> tile.Tile

Returns the indexed (0..=4) kan draw.

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 const max_num_draws: Int

The maximum number of draws, from front and back

pub fn to_list(wall: Wall) -> List(tile.Tile)

Returns the inner list.

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

pub fn ura_dora_indicators(wall: Wall) -> List(tile.Tile)

Returns the entire ura-dora indicator section of the wall as a list. This does not handle final revealing of ura-dora indicators.

✨ Search Document