@idealic/poker-engine
Version:
Professional poker game engine and hand evaluator with built-in iterator utilities
142 lines • 6.19 kB
JavaScript
import { canCheck, canCall, canBet, canRaise, canFold, isPlayerTurn, isAwaitingDealer, } from '../utils/validation';
import { getRemainingPlayers } from '../utils/position';
/**
* Unified validation function for all game commands.
* This is a catch-all method that validates whether a specific command can be executed
* in the current game state.
*
* @param game - The current game state
* @param command - The command name to validate
* @param args - Additional arguments required by specific commands
* @returns true if the command is valid and can be executed, false otherwise
*
* @example
* // Check if player 0 can fold
* const canPlayerFold = Poker.Game.can(game, 'fold', 0);
*
* // Check if player 1 can bet 100 chips
* const canPlayerBet = Poker.Game.can(game, 'bet', 1, 100);
*
* // Check if dealer can deal board cards
* const canDealBoard = Poker.Game.can(game, 'dealBoard', ['Ah', 'Kh', 'Qh']);
*/
export function can(game, command, ...args) {
switch (command) {
case 'fold': {
const [playerIndex] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
return isPlayerTurn(game, playerIndex) && canFold(game, playerIndex);
}
case 'check': {
const [playerIndex] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
return isPlayerTurn(game, playerIndex) && canCheck(game, playerIndex);
}
case 'call': {
const [playerIndex] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
return isPlayerTurn(game, playerIndex) && canCall(game, playerIndex);
}
case 'bet': {
const [playerIndex, amount] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
if (typeof amount !== 'number' || amount <= 0) {
return false;
}
const player = game.players[playerIndex];
const availableStack = player.stack + player.currentBet;
return (isPlayerTurn(game, playerIndex) &&
canBet(game, playerIndex) &&
amount <= availableStack);
}
case 'raise': {
const [playerIndex, amount] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
if (typeof amount !== 'number' || amount <= 0) {
return false;
}
const player = game.players[playerIndex];
const availableStack = player.stack + player.currentBet;
const minRaiseAmount = game.bet * 2 - player.currentBet;
return (isPlayerTurn(game, playerIndex) &&
canRaise(game, playerIndex) &&
amount >= minRaiseAmount &&
amount <= availableStack);
}
case 'dealBoard': {
const [cards] = args;
if (!Array.isArray(cards) || cards.length === 0) {
return false;
}
// Can deal board if it's dealer's turn and we need community cards
if (!isAwaitingDealer(game)) {
return false;
}
// Check if we need board cards (not all hole cards dealt yet, or betting round complete)
const activePlayers = getRemainingPlayers(game);
const allPlayersHaveCards = activePlayers.every(p => p.cards.length > 0);
if (!allPlayersHaveCards) {
return false; // Need to deal hole cards first
}
// Can deal board if betting is complete and we haven't dealt all board cards
return game.isBettingComplete && game.board.length < 5;
}
case 'dealHoleCards': {
const [playerIndex, cards] = args;
if (typeof playerIndex !== 'number' || playerIndex < 0 || playerIndex >= game.players.length) {
return false;
}
if (!Array.isArray(cards) || cards.length === 0) {
return false;
}
// Can deal hole cards if it's dealer's turn and the player needs cards
if (!isAwaitingDealer(game)) {
return false;
}
const player = game.players[playerIndex];
return !player.isInactive && player.cards.length === 0;
}
case 'dealStreet': {
// Can deal street if it's dealer's turn and conditions are met
if (!isAwaitingDealer(game)) {
return false;
}
// Check if all players have cards
const activePlayers = getRemainingPlayers(game);
const allPlayersHaveCards = activePlayers.every(p => p.cards.length > 0);
if (!allPlayersHaveCards) {
return false; // Need to deal hole cards first
}
// Can deal next street if betting is complete and more cards are needed
return game.isBettingComplete && game.board.length < 5;
}
case 'showCards': {
// Can show cards if it's showdown time
if (!isAwaitingDealer(game)) {
return false;
}
const activePlayers = getRemainingPlayers(game);
// Need at least 2 players for showdown
if (activePlayers.length < 2) {
return false;
}
// Can show cards if all board cards are dealt and there are players who haven't shown
const hasUnshownPlayers = activePlayers.some(p => !p.hasShownCards && p.cards.length > 0);
return game.board.length === 5 && hasUnshownPlayers;
}
default:
// Unknown command
return false;
}
}
//# sourceMappingURL=validation.js.map