using Hokm.Engine; // All-AI simulation to validate the C# engine port (mirrors scripts/sim.ts). var rng = new Random(12345); int N = 300; int totalRounds = 0; for (int i = 0; i < N; i++) { var (rounds, tricks) = PlayMatch(rng); totalRounds += rounds; if (tricks <= 0) throw new Exception("no tricks played"); } Console.WriteLine($"OK: {N} matches completed. avg rounds/match = {(double)totalRounds / N:0.0}"); static (int rounds, int tricks) PlayMatch(Random rng) { var g = Rules.CreateInitial(new[] { "P0", "P1", "P2", "P3" }, 7); Rules.SelectHakem(g, rng); Rules.DealForTrump(g, rng); int rounds = 0, tricks = 0, guard = 0; while (g.Phase != Phase.MatchOver) { if (++guard > 200000) throw new Exception("loop guard tripped"); switch (g.Phase) { case Phase.ChoosingTrump: Rules.ChooseTrump(g, Ai.ChooseTrump(g.Players[g.Hakem!.Value].Hand)); break; case Phase.Playing: int seat = g.Turn!.Value; Rules.PlayCard(g, seat, Ai.ChooseCard(g, seat)); break; case Phase.TrickComplete: tricks++; if (g.CurrentTrick.Count != 4) throw new Exception("trick not full"); Rules.AdvanceAfterTrick(g, 2); break; case Phase.RoundOver: rounds++; if (g.RoundTricks[0] + g.RoundTricks[1] > 13) throw new Exception("too many tricks"); Rules.StartNextRound(g, rng); break; default: throw new Exception("unexpected phase: " + g.Phase); } } return (rounds, tricks); }