@idealic/poker-engine
Version:
Professional poker game engine and hand evaluator with built-in iterator utilities
86 lines • 3.43 kB
JavaScript
/**
* Game analytics extension demonstrating module augmentation pattern.
* This file shows how to extend the Game namespace with additional functionality.
*/
/**
* Calculate the approximate win probability for a player based on game state.
* This is a simplified implementation for demonstration purposes.
*
* @param game - Current game state
* @param playerId - Name of the player to calculate win probability for
* @returns Win probability as a decimal between 0 and 1
*/
export function getWinProbability(game, playerId) {
// Find the player in the game
const player = game.players.find(p => p.name === playerId);
if (!player || player.hasFolded) {
return 0;
}
// Simple heuristic based on relative stack size and pot odds
const totalActiveStacks = game.players
.filter(p => !p.hasFolded && !p.isInactive)
.reduce((sum, p) => sum + p.stack, 0);
if (totalActiveStacks === 0)
return 0.5; // Neutral probability if no stacks
const playerStackRatio = player.stack / totalActiveStacks;
const potOdds = game.bet > 0 ? game.bet / (game.pot + game.bet) : 0.5;
// Combine stack strength with pot odds for a rough win probability
return Math.min(0.95, Math.max(0.05, (playerStackRatio * 0.7) + (potOdds * 0.3)));
}
/**
* Calculate the current pot odds for the next player to act.
*
* @param game - Current game state
* @returns Pot odds as a decimal (amount to call / total pot after call)
*/
export function getPotOdds(game) {
if (game.bet === 0) {
return 0; // No bet to call
}
const totalPotAfterCall = game.pot + game.bet;
return game.bet / totalPotAfterCall;
}
/**
* Calculate expected value for a call based on win probability and pot odds.
*
* @param game - Current game state
* @param playerId - Name of the player considering the call
* @returns Expected value as a positive or negative number
*/
export function getCallExpectedValue(game, playerId) {
const winProbability = getWinProbability(game, playerId);
const potOdds = getPotOdds(game);
if (game.bet === 0)
return 0; // No call needed
const potSizeAfterCall = game.pot + game.bet;
const expectedWin = winProbability * potSizeAfterCall;
const costToCall = game.bet;
return expectedWin - costToCall;
}
/**
* Get game phase analysis including aggression factors and betting patterns.
*
* @param game - Current game state
* @returns Analysis object with various game metrics
*/
export function getGameAnalysis(game) {
const activePlayers = game.players.filter(p => !p.hasFolded && !p.isInactive);
const totalActiveStacks = activePlayers.reduce((sum, p) => sum + p.stack, 0);
const averageStack = activePlayers.length > 0 ? totalActiveStacks / activePlayers.length : 0;
// Simple aggression factor based on pot size relative to blinds
const bigBlind = game.minBet;
const aggressionFactor = game.pot / (bigBlind * 2); // Pot size in big blinds
const potToStackRatio = averageStack > 0 ? game.pot / averageStack : 0;
return {
phase: game.street,
aggressionFactor,
averageStack,
potToStackRatio,
activePlayers: activePlayers.length
};
}
Game.getWinProbability = getWinProbability;
Game.getPotOdds = getPotOdds;
Game.getCallExpectedValue = getCallExpectedValue;
Game.getGameAnalysis = getGameAnalysis;
//# sourceMappingURL=analytics.js.map