fertig-classic-games/src/games/bingo/BingoAI.js

34 lines
1.2 KiB
JavaScript

// Bingo AI — opponents auto-daub inside BingoLogic.drawBall, so the only AI
// "decision" is the claim race: how long an eligible opponent waits before
// shouting BINGO. That delay is the window in which the human can beat them.
import { hasCompletedLine } from './BingoLogic.js';
// Non-human seats that currently hold a completed line.
export function aiEligibleSeats(state) {
return state.players
.filter((p) => !p.isHuman && hasCompletedLine(p))
.map((p) => p.seat);
}
// Suspense delay (ms) before an eligible AI auto-calls Bingo. Jittered around
// ~1.5s; sharper (higher-skill) opponents react a touch faster.
export function chooseClaimDelayMs(seat, skill = 3) {
const base = 1700 - skill * 120;
return base + Math.random() * 500;
}
// When the human forfeits (advances without claiming) and ≥1 AI is eligible,
// the fastest reactor wins. Tie-break by lowest seat for determinism.
export function pickEarliestAIWinner(state) {
const seats = aiEligibleSeats(state);
if (seats.length === 0) return null;
let best = seats[0];
let bestDelay = chooseClaimDelayMs(best);
for (let i = 1; i < seats.length; i++) {
const d = chooseClaimDelayMs(seats[i]);
if (d < bestDelay) { best = seats[i]; bestDelay = d; }
}
return best;
}