The test/original_vs_port/ framework is a specialized testing suite designed to ensure behavioral equivalence between the original CoffeeScript implementation of mjai-manue and the Go port. It operates by generating game logs from the original engine and replaying those scenarios through the Go port to detect discrepancies in decision-making logic, including evaluation values (expPt, avgRank) and final action selection.
The framework consists of two primary stages: log generation via Docker Compose and log comparison via a Go-based analysis tool.
gen_log)The gen_log component uses Docker Compose to orchestrate a complete MJAI environment. It pits one instance of the original mjai-manue against three instances of the akochan AI to produce realistic game scenarios test/original_vs_port/gen_log/compose.yaml15-45
System Entity Mapping: Log Generation
Sources: test/original_vs_port/gen_log/compose.yaml1-52 test/original_vs_port/gen_log/server/Dockerfile1-38 test/original_vs_port/gen_log/akochan/Dockerfile1-75
compare)The compare tool is a Go program that reads the generated .mjson logs. It identifies the player named Manue014 (default) and, for every turn that player took, feeds the preceding game state into the Go port's ManueAgent test/original_vs_port/compare/main.go40-48
Code Entity Mapping: Comparison Logic
Sources: test/original_vs_port/compare/comparer.go89-165 test/original_vs_port/compare/main.go16-68 test/original_vs_port/compare/action.go1-120
The server is based on the standard Ruby mjai gem. The Dockerfile applies patches to ensure compatibility with modern Ruby (e.g., Ruby 4.0) test/original_vs_port/gen_log/server/Dockerfile3-16
URI.decode to URI.decode_www_form_component, fixes ERB.new call signatures for Ruby 4 compatibility, and relaxes strict version constraints in mjai.gemspec test/original_vs_port/gen_log/server/patch.sh4-19Three instances of akochan serve as opponents.
libai.so using Makefile_Linux test/original_vs_port/gen_log/akochan/Dockerfile31-41system.exe mjai_client in a loop for the specified NUM_GAMES test/original_vs_port/gen_log/akochan/run_akochan.sh11-19The comparer handles the complexities of MJAI protocol differences (e.g., field order, optional fields) by normalizing both original and Go actions before comparison test/original_vs_port/compare/action.go14-45
| Function | Responsibility |
|---|---|
normalizeRawAction | Unmarshals raw JSON into a normalizedAction struct, stripping non-essential fields test/original_vs_port/compare/action.go14 |
actionsEqual | Compares type, actor, tile (pai), and consumed tiles for melds test/original_vs_port/compare/action.go53 |
flushPendingBeforeNonSelf | Handles "implicit passes" where the Go port might suggest a call (chi/pon) that the original ignored test/original_vs_port/compare/comparer.go200 |
isPreemptedByHigherPriorityAction | Accounts for MJAI priority (Win > Pon > Chi) when comparing suggested reactions test/original_vs_port/compare/comparer.go232 |
Sources: test/original_vs_port/compare/comparer.go182-254 test/original_vs_port/compare/action.go14-120
A static analysis and comparison audit revealed several critical differences between the CoffeeScript original and the Go port:
reachMode): The original AI adds 1 Han for potential Riichi in its heuristic (reachMode=default) even when not yet in Tenpai. The Go port initially mixed this up with "pruning to Tenpai," causing it to undervalue flexible hands test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md33-38getHoraFactorsDist where it assigns Tsumo probability to the player instead of the actual winner, leading the original to undervalue its own expected points (expPt) test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md46-51seedRandom("") for every getHoraEstimation, whereas the Go port uses a single PCG source per game test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md53-57afterDiscardHand test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md59-63Sources: test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md1-162
The tool supports JSONv2 for faster parsing and requires the embedded game stats and danger tree test/original_vs_port/compare/main.go29-38
test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md19-25
Sources: test/original_vs_port/compare/main.go12-68 test/original_vs_port/compare/DIFF_INVESTIGATION_REPORT.md1-27