xiangting 5.0.3

A library for calculating the deficiency number (a.k.a. xiàngtīng number, 向聴数).
Documentation

xiangting

Crate Minimum Supported Rust Version API API Ask DeepWiki

A library for calculating the deficiency number (a.k.a. xiàngtīng number, 向聴数).

Documentation:

References

Language Bindings

Installation

cargo add xiangting

Usage

Basic Usage

The hand is represented as an array of [u8; 34], where each element represents the count of a specific tile. The correspondence between the index and the tile is shown in the table below.

Index 0 1 2 3 4 5 6 7 8
Tile 1m 2m 3m 4m 5m 6m 7m 8m 9m
Index 9 10 11 12 13 14 15 16 17
Tile 1p 2p 3p 4p 5p 6p 7p 8p 9p
Index 18 19 20 21 22 23 24 25 26
Tile 1s 2s 3s 4s 5s 6s 7s 8s 9s
Index 27 28 29 30 31 32 33
Tile East (1z) South (2z) West (3z) North (4z) White (5z) Green (6z) Red (7z)

Calculates the replacement number, which is equal to the deficiency number (a.k.a. xiàngtīng number, 向聴数) + 1.

use xiangting::{PlayerCount, calculate_replacement_number};

fn main() {
    // 123m456p789s11222z
    let hand: [u8; 34] = [
        1, 1, 1, 0, 0, 0, 0, 0, 0, // m
        0, 0, 0, 1, 1, 1, 0, 0, 0, // p
        0, 0, 0, 0, 0, 0, 1, 1, 1, // s
        2, 3, 0, 0, 0, 0, 0, // z
    ];

    let replacement_number = calculate_replacement_number(&hand, &PlayerCount::Four).unwrap();
    assert_eq!(replacement_number, 0u8);
}

Necessary and Unnecessary Tiles

It is also possible to calculate necessary or unnecessary tiles together with the replacement number.

  • Necessary tiles

    • Tiles needed to win with the minimum number of replacements
    • Tiles that reduce the replacement number when drawn
    • In Japanese, these are referred to as 有効牌 (yūkōhai) or 受け入れ (ukeire)
  • Unnecessary tiles

    • Tiles not needed to win with the minimum number of replacements
    • Tiles that can be discarded without changing the replacement number
    • In Japanese, these are referred to as 不要牌 (fuyōhai) or 余剰牌 (yojōhai)
use xiangting::{PlayerCount, calculate_necessary_tiles, calculate_unnecessary_tiles};

fn main() {
    // 199m146779p12s246z
    let hand: [u8; 34] = [
        1, 0, 0, 0, 0, 0, 0, 0, 2, // m
        1, 0, 0, 1, 0, 1, 2, 0, 1, // p
        1, 1, 0, 0, 0, 0, 0, 0, 0, // s
        0, 1, 0, 1, 0, 1, 0, // z
    ];

    let (replacement_number1, necessary_tiles) =
        calculate_necessary_tiles(&hand, &PlayerCount::Four).unwrap();
    let (replacement_number2, unnecessary_tiles) =
        calculate_unnecessary_tiles(&hand, &PlayerCount::Four).unwrap();

    assert_eq!(replacement_number1, 5);
    assert_eq!(replacement_number1, replacement_number2);
    assert_eq!(necessary_tiles, 0b1111111_100000111_111111111_100000111); // 1239m123456789p1239s1234567z
    assert_eq!(unnecessary_tiles, 0b0101010_000000011_101101001_000000001); // 1m14679p12s246z
}

Support for Three-Player Mahjong

In three-player mahjong, the tiles from 2m (二萬) to 8m (八萬) are not used.

use xiangting::{PlayerCount, calculate_necessary_tiles, calculate_unnecessary_tiles};

fn main() {
    // 1111m111122233z
    let hand: [u8; 34] = [
        4, 0, 0, 0, 0, 0, 0, 0, 0, // m
        0, 0, 0, 0, 0, 0, 0, 0, 0, // p
        0, 0, 0, 0, 0, 0, 0, 0, 0, // s
        4, 3, 2, 0, 0, 0, 0, // z
    ];

    let (rn_4p, nt_4p) = calculate_necessary_tiles(&hand, &PlayerCount::Four).unwrap();
    let (_, ut_4p) = calculate_unnecessary_tiles(&hand, &PlayerCount::Four).unwrap();
    assert_eq!(rn_4p, 2u8);
    assert_eq!(nt_4p, 0b0000000_000000000_000000000_000000110); // 23m
    assert_eq!(ut_4p, 0b0000001_000000000_000000000_000000000); // 1z

    let (rn_3p, nt_3p) = calculate_necessary_tiles(&hand, &PlayerCount::Three).unwrap();
    let (_, ut_3p) = calculate_unnecessary_tiles(&hand, &PlayerCount::Three).unwrap();
    assert_eq!(rn_3p, 3u8);
    assert_eq!(nt_3p, 0b1111100_111111111_111111111_100000000); // 9m123456789p123456789s34567z
    assert_eq!(ut_3p, 0b0000001_000000000_000000000_000000001); // 1m1z
}

Build tables and maps (For developers only)

xiangting$ scripts/build_table.sh && scripts/build_map.sh

License

Copyright (c) Apricot S. All rights reserved.

Licensed under the MIT license.