UNPKG

binmat

Version:
131 lines (130 loc) 3.4 kB
import { doMove } from "./doMove.js" import { makeState } from "./makeState.js" import { parseMove } from "./parseMove.js" import { StatusCodeMessages, StatusCode, Role, MoveKind } from "./shared.js" import { generateArgsForDefender, generateArgsForAttacker } from "./generateArgs.js" import "./doMoveCombat.js" import "./doCombat.js" import "@samual/lib/shuffle" import "./doMoveDiscard.js" import "./doMoveDraw.js" import "./doMovePass.js" import "./doMovePlay.js" import "./doMovePlayFaceUp.js" import "@samual/lib/assert" function simulateGame( defenderBrain, attackerBrain, { timeLimit: timeLimit = 5e3, defenderUserName: defenderUserName = "defender", attackerUserName: attackerUserName = "attacker", noThrow: noThrow = !1, onMove: onMove, state: state = makeState(), defenderBinlog: defenderBinlog = [], attackerBinlog: attackerBinlog = [] } = {} ) { let endTime, winner, madeMove for (;;) { if ( ((madeMove = !1), (endTime = Date.now() + timeLimit), defenderBrain( { caller: defenderUserName, this_script: `${defenderUserName}.binmat_brain`, cols: 0, rows: 0, calling_script: null }, generateArgsForDefender(state, defenderUserName, attackerUserName, [ ...defenderBinlog, ...attackerBinlog ]), xform ), !madeMove) ) { if (!noThrow) throw new Error("defender brain did not attempt to make a move") doDefaultMove() } if ((onMove?.(state, defenderBinlog), winner)) return winner if ( ((madeMove = !1), (endTime = Date.now() + timeLimit), attackerBrain( { caller: attackerUserName, this_script: `${attackerUserName}.binmat_brain`, cols: 0, rows: 0, calling_script: null }, generateArgsForAttacker(state, defenderUserName, attackerUserName, [ ...attackerBinlog, ...defenderBinlog ]), xform ), !madeMove) ) { if (!noThrow) throw new Error("attacker brain did not attempt to make a move") doDefaultMove() } if ((onMove?.(state, attackerBinlog), winner)) return winner } function xform({ op: op }) { if (madeMove) { if (noThrow) return { ok: !1 } throw new Error("only 1 move per turn") } if (((madeMove = !0), Date.now() > endTime)) { if (noThrow) return doDefaultMove() throw new Error("made move too late") } let move try { move = parseMove(op) } catch (error) { if (noThrow) return doDefaultMove() throw error } const result = doMove(state, move) switch (result.status) { case StatusCode.Ok: break case StatusCode.AttackerWin: winner = Role.Attacker break case StatusCode.DefenderWin: winner = Role.Defender break default: if (noThrow) return doDefaultMove() throw new Error(StatusCodeMessages[result.status]) } return ( (state.turn % 2) + 1 == Role.Defender ? (attackerBinlog = result.binlog) : (defenderBinlog = result.binlog), { ok: !0 } ) } function doDefaultMove() { const result = doMove(state, { kind: MoveKind.Pass }) switch (result.status) { case StatusCode.Ok: break case StatusCode.DefenderWin: winner = Role.Defender break default: throw new Error(`unexpected status code ${result.status}`) } return ( (state.turn % 2) + 1 == Role.Defender ? (attackerBinlog = result.binlog) : (defenderBinlog = result.binlog), { ok: !1 } ) } } export { simulateGame }