Skip to content

pauljxtan/toitoi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

toitoi

Build Status

API docs | Scoring demo

A Riichi mahjong library in Rust. (Very WIP.)

For now, it handles most hand scoring scenarios under standard rules. In addition to the tests included in this repo, the logic has also been tested extensively on about a million Tenhou game logs, and seems to be accurate outside of super-edge cases. While this has not yet been heavily optimized, it is already reasonably performant, because Rust.

The plan is to eventually expand this library into a full game engine to be potentially used for reinforcement learning and other computational experiments, and, well, actually playing the game itself.

Here's a demo of a Wasm-based hand calculator that uses this library under the hood.

Running

This project is built against stable Rust.

Run tests:

$ make test

Format code:

$ make fmt

API example

Here's an example that scores a hand with 1 han and 110 fu:

  • Closed tiles: 4-man, 5-man, 6-man, ton, ton, nan, nan
  • Calls:
    • Closed kan on 1-sou
    • Closed kan on chun
  • Agari: ton (by ron)
  • Round wind: nan
  • Player wind: nan
use toitoi::score::score;
use toitoi::tile::{tile_from_string, tiles_from_string};
use toitoi::types::{Call, FuReason, HandContext, HanReason, Limit, Points, Yaku};

let tiles = tiles_from_string("456m1122z");
let calls = vec![
    Call::ankan(tile_from_string("1s")),
    Call::ankan(tile_from_string("7z")),
];
let context = HandContext {
    winning_tile: tile_from_string("1z"),
    is_tsumo: false,
    round_wind: tile_from_string("2z"),
    player_wind: tile_from_string("2z"),
    ..Default::default()
};

let results = score(&tiles, &calls, &context);

assert_eq!(results.len(), 1);

assert_eq!(results[0].fu(), 110);
assert_eq!(results[0].han(), 1);
assert_eq!(results[0].limit(), Limit::NoLimit);
assert_eq!(results[0].points(), Points::Ron(3600));

assert_eq!(results[0].fu_reasons(), vec![
    (FuReason::Base, 20),
    (FuReason::OpenTripletHonours, 4),
    (FuReason::YakuhaiPairRoundWind, 2),
    (FuReason::YakuhaiPairPlayerWind, 2),
    (FuReason::ClosedQuadTerminals, 32),
    (FuReason::ClosedQuadHonours, 32),
    (FuReason::ClosedRon, 10),
    (FuReason::RoundUp, 8),
]);
assert_eq!(results[0].han_reasons(), vec![(HanReason::Yaku(Yaku::Chun), 1)]);

Releases

No releases published

Packages

No packages published

Languages