Giter VIP home page Giter VIP logo

tsumonya's Introduction

Tsumonya - ultra-high throughput mahjong hand calculator

Tsumonya is a mahjong-related C++ library that calculates the score for a given winning hand (和了形). The main feature of this library is its ultra-high throughput, i.e., it focuses on dramatically reducing the average computation time for a single score calculation when calling many consecutive score calculation routines. On the other hand, the library sacrifices a significant amount of reaction time, or latency, for a single computation routine call. In addition, this library consumes an ridicuously large amount of storage (~26GB). Therefore, users are requested to carefully determine whether this library is suitable to their individual use cases.

Ultra-high throughput is not likely to be required for ordinary mahjong score calculations. However, ultra-high throughput may be required when running large-scale simulations for the development, training, and evaluation of mahjong AIs. In these cases, the score calculation is called not only once at the end of each round in simulations, but also many times to determine whether a zimo (自摸) or rong (ロン) is possible when one of the players has a ready hand and every time they draws a tile or another player discards a tile. Therefore, an ultra-high throughput implementation in calling a large number of scoring routines would contribute significantly to simulation speed-up.

The implementation is based on an idea of computing mahjong scores only by simple array indexing. In other words, this library pre-computes the fu (符) and fan (飜) for ALL POSSIBLE MAHJONG WINNING HANDS and stores them in a huge array. In this way, it completely omits the computationally expensive processes normally required for mahjong score calculation, such as member (面子, menzi) decomposition, calculation of fu, determination of hand types (Yaku, 役), calculation of fan, logic to resolve ambiguities in member decomposition for an winning hand based on the highest point principle (高点法), and others.

How to use

First, set up git large file storage.

$ git lfs install

Next, clone this repository.

$ git clone https://github.com/Cryolite/tsumonya
$ cd tsumonya

Then, decompress map.bin.gz.

tsumonya$ gunzip -k map.bin.gz

Finally, add the path to the top directory of this repository to the set of the include paths, and include the <tsumonya/calculator.hpp> header file.

Reference

namespace Tsumonya{

using Hand = std::array<std::uint_fast8_t, 34u>;
using ChiList = std::array<std::uint_fast8_t, 21u>;
using PengList = std::array<std::uint_fast8_t, 34u>;
using GangList = std::array<std::uint_fast8_t, 34u>;

enum Situation
  : std::uint_fast16_t;

inline constexpr Situation zimo;
inline constexpr Situation rong;
inline constexpr Situation liqi;
inline constexpr Situation qianggang;
inline constexpr Situation lingshang_kaihua;
inline constexpr Situation haidi_moyue;
inline constexpr Situation haidi_laoyue;
inline constexpr Situation double_liqi;
inline constexpr Situation yifa;
inline constexpr Situation tianhu;
inline constexpr Situation dihu;

class Calculator
{
public:
  explicit Calculator(char const *map_path);
  explicit Calculator(std::string const &map_path);
  explicit Calculator(std::filesystem::path const &map_path);
  std::pair<std::uint_fast8_t, std::uint_fast8_t> operator()(
    Hand const &hand, ChiList const &chi_list, PengList const &peng_list,
    GangList const &angang_list, GangList const &minggang_list, std::uint_fast8_t hupai,
    std::uint_fast8_t num_red_tiles, Situation situation) const;
};

}

Hand

The Hand type represents a set of tiles in a hand. It MUST NOT contain melded tiles (副露牌) nor the winning tile (和牌). This is an array type with 34 elements. The 0-th element MUST indicate the number of the 1 Character tile (一萬, 1m), the 1st element the number of the 2 Character tile (二萬, 2m), and so on.

ChiList

The ChiList type represents a set of chews (chi, 吃, チー). This is an array type with 21 elements. The 0-th element MUST indicate the number of the chew (1m, 2m, 3m), the 1st element the number of the chews (2m, 3m, 4m), and so on.

PengList

The PengList type represents a set of pengs (pon, 碰, ポン). This is an array type with 34 elements. The 0-th element MUST indicate the number of the peng (1m, 1m, 1m), the 1st element the number of the peng (2m, 2m, 2m), and so on.

GangList

The GangList type represents a set of kongs (gang, 槓, カン). This is an array type with 34 elements. The 0-th element MUST indicate the number of the kong (1m, 1m, 1m, 1m), the 1st element the number of the kong (2m, 2m, 2m, 2m), and so on.

Situation

The Situation enum type is used to specifiy situation, especially hand types (yaku, 役), that cannot be determined from just the hand, melded tiles, and the winning tile. Multiple objects of the type Situation can be combined with operator|.

zimo

zimo represents a self-drawn win (自摸和).

rong

rong represents a dealt-in win (栄和).

liqi

liqi represents a riichi (立直) declaration.

qianggang

qianggang represents a robbing of a kong (槍槓).

lingshang_kaihua

lingshang_kaihua represents an after-kong win (嶺上開花).

haidi_moyue

haidi_moyue represents a last-tile-draw win (海底撈月).

haidi_laoyue

haidi_moyue represents a last-tile-discard win (河底撈魚).

double_liqi

liqi represents a double riichi (ダブル立直) declaration.

yifa

yifa represents Ippatsu (一発).

tianhu

tianhu represents a heavenly hand (天和).

dihu

dihu represents an earthly hand (地和).

Calculator::Calculator(char const *map_path)

Calculator::Calculator(std::string const &map_path)

Calculator::Calculator(std::filesystem::path const &map_path)

These are the constructors of Calculator. map_path MUST specify the path to the map.bin file.

std::pair<std::uint_fast8_t, std::uint_fast8_t> Calculator::operator()(Hand const &hand, ChiList const &chi_list, PengList const &peng_list, GangList const &angang_list, GangList const &minggang_list, std::uint_fast8_t hupai, std::uint_fast8_t num_red_tiles, Situation situation)

This function calculates fu (符) and fan (飜) for the winning situation represented by the arguments. hand MUST specify the hand, chi_list the set of chews, peng_list the set of pengs, angang_list the set of closed kongs, minggang_list the set of open kongs, hupai the winning tile, num_red_tiles the number of red tiles, and situation the situation of the win.

The return value is a pair of fu and fan. If the situation represented by the arguments is not a win, a pair of 0s is returned.

Performance comparison

It is approximately 100 times faster on average than the mahjong Python package (version 1.1.10).

Background theory

The most important core of the theory behind this library is the implementation of a near-minimal perfect (collisionless) hash function for the set of all possible mahjong winning hands. The current implementation maps an winning hand to a natural number in the range [0, 1062518406). Therefore, by preparing an array with 13 * 1062518406 elements, where the number 13 means that the library has additional information to identify which tile of each winning hand is the winning tile, and by calling some score calculation routine for each winning hand and recording the result of the routine in the [i * 13, i * 13 + 13)-th elements of the array (where i is the hash of the winning hand), when calculating scores, it is only necessary to calculate the hash of the given winning hand and access the array element.

Build from scratch (For developers only)

Execute the following commands with the top directory of the working tree of this repository as the current directory. Note that the build process can take a verrrrrrrrrry long time (~20 days).

tsumonya$ docker build --pull -t cryolite/tsumonya .
tsumonya$ docker run -v /path/to/working-tree:/workspace/tsumonya -it --rm cryolite/tsumonya

tsumonya's People

Contributors

cryolite avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

tsumonya's Issues

Interested in contributing to iQL project for Japanese Mahjong

Hello Cryolite,

I noticed that you are starting new work on iQL for Japanese Mahjong and have created a new repository for it. I would like to offer my help as I have some experience with Japanese Mahjong and I am interested in contributing to this project. Additionally, I have experience with implementing iQL in Starcraft2 AI.

I recently obtained my master's degree in GIS from UIUC, and I will be starting my Ph.D. in AI at UCSD this May.

Please let me know if there is anything specific you need help with, or if you have any suggestions on how I could get involved.

Thank you for your time and consideration. I look forward to hearing back from you.

Best regards,
Lixuanwu

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.