← poker-tutor
import Foundation
import PokerCore
import PokerAI
import PokerCoach
import PokerTests
import PokerSession
/// Command-line driver for the poker engine. `pokerlab test` runs the suites;
/// `pokerlab tournament` plays one out so the engine can be watched working.
let args = Array(CommandLine.arguments.dropFirst())
let command = args.first ?? "test"
func flag(_ name: String) -> Bool { args.contains("--\(name)") }
func value(_ name: String) -> String? {
guard let i = args.firstIndex(of: "--\(name)"), i + 1 < args.count else { return nil }
return args[i + 1]
}
/// `--format cash` sits the session at a cash table (`--structure fixedLimit|potLimit|noLimit`,
/// `--stakes 50/100`); anything else is the tournament the commands always played.
let labFormat: AppVariant.Format = value("format") == "cash" ? .cash : .tournament
let labStructure: BettingStructure = BettingStructure(rawValue: value("structure") ?? "noLimit") ?? .noLimit
let labSetup: CashSetup = {
var setup = CashSetup.standard
setup.structure = labStructure
if let stakes = value("stakes")?.split(separator: "/").compactMap({ Int($0) }), stakes.count == 2 {
setup.stakes = BlindLevel(smallBlind: stakes[0], bigBlind: stakes[1])
}
return setup
}()
switch command {
case "test":
let ok = runAllTests(verbose: flag("verbose"), filter: value("filter"))
exit(ok ? 0 : 1)
case "tournament":
let players = Int(value("players") ?? "9") ?? 9
let seed = UInt64(value("seed") ?? "1") ?? 1
let verbose = flag("verbose")
runTournament(players: players, seed: seed, verbose: verbose)
case "seat-sweep":
runSeatSweep(playerName: value("player") ?? "control",
hands: Int(value("hands") ?? "6000") ?? 6000,
seedCount: Int(value("seeds") ?? "4") ?? 4,
firstSeed: UInt64(value("seed") ?? "11") ?? 11,
rung: Int(value("rung") ?? "0") ?? 0)
case "shootout":
runShootout(hands: Int(value("hands") ?? "3000") ?? 3000, seed: UInt64(value("seed") ?? "1") ?? 1,
stack: Int(value("stack") ?? "10000") ?? 10000, structure: labStructure)
case "coach":
if labFormat == .cash { AppVariant.use(.pokerTutorCash) }
let coachHands = Int(value("hands") ?? "320") ?? 320
let coachSeed = UInt64(value("seed") ?? "4242") ?? 4242
let coachSamples = Int(value("samples") ?? "4") ?? 4
let coachRung = Int(value("rung") ?? "0") ?? 0
runCoach(hands: coachHands, seed: coachSeed, playerName: value("player") ?? "control",
samples: coachSamples, showProfile: flag("profile"),
format: labFormat, setup: labSetup, rung: coachRung,
keepEveryReview: flag("all"), breakdown: flag("breakdown"))
case "sweep":
runSweep(playerName: value("player") ?? "control", againstName: value("against"),
hands: Int(value("hands") ?? "4000") ?? 4000,
seedCount: Int(value("seeds") ?? "12") ?? 12,
firstSeed: UInt64(value("seed") ?? "4242") ?? 4242,
format: labFormat, setup: labSetup, rung: Int(value("rung") ?? "0") ?? 0)
case "calibrate":
runCalibration(hands: Int(value("hands") ?? "1200") ?? 1200,
seedCount: Int(value("seeds") ?? "6") ?? 6,
firstSeed: UInt64(value("seed") ?? "11") ?? 11,
format: labFormat, setup: labSetup)
case "demo-history":
runDemoHistory(playerName: value("player") ?? "loose",
seed: UInt64(value("seed") ?? "9") ?? 9,
hands: Int(value("hands") ?? "320") ?? 320,
out: value("out") ?? "demo-hands.jsonl",
format: labFormat, setup: labSetup)
case "assess":
if labFormat == .cash { AppVariant.use(.pokerTutorCash) }
runAssessment(playerName: value("player") ?? "control",
seed: UInt64(value("seed") ?? "11") ?? 11,
hands: Int(value("hands") ?? "40") ?? 40,
setupID: value("setup"),
cash: labFormat == .cash ? labSetup : nil)
case "ablate":
let styleName = value("style") ?? "solidRegular"
let style = Personality.allCases.first { $0.rawValue.lowercased() == styleName.lowercased() } ?? .solidRegular
runAblation(hands: Int(value("hands") ?? "400") ?? 400, seed: UInt64(value("seed") ?? "57") ?? 57,
personality: style, seats: Int(value("seats") ?? "6") ?? 6)
case "diagnose":
runDiagnose(hands: Int(value("hands") ?? "800") ?? 800, seed: UInt64(value("seed") ?? "57") ?? 57,
stack: Int(value("stack") ?? "4000") ?? 4000, samples: Int(value("samples") ?? "0") ?? 0)
case "gen-preflop":
generatePreflopTable(trials: Int(value("trials") ?? "20000") ?? 20000)
case "hand":
runSingleHand(seed: UInt64(value("seed") ?? "1") ?? 1, players: Int(value("players") ?? "6") ?? 6)
default:
print("""
pokerlab — poker engine driver
pokerlab test [--verbose] [--filter <text>]
pokerlab tournament [--players N] [--seed N] [--verbose]
pokerlab hand [--players N] [--seed N]
pokerlab assess [--player <flaw>] [--seed N] [--hands N]
any command that sits a session: --format cash [--structure fixedLimit|potLimit|noLimit] [--stakes 50/100]
pokerlab shootout --structure fixedLimit
""")
exit(1)
}