feat(SCOPONE-0009): complete iteration 0 dealer AI

This commit is contained in:
Giancarmine Salucci
2026-04-08 21:50:40 +02:00
parent c9accb7ae4
commit d0a44d295a
7 changed files with 597 additions and 174 deletions

View File

@@ -1,6 +1,6 @@
import {
Card, Suit, SUITS, Player, PlayerIndex, GameState,
TeamScore, ScoreBreakdown, PRIMIERA_VALUES, Capture
TeamScore, ScoreBreakdown, PRIMIERA_VALUES, Capture, DealerRelativeRole
} from './types';
// ---------------------------------------------------------------------------
@@ -76,8 +76,38 @@ export function canCapture(played: Card, table: Card[]): boolean {
// Game state initialisation
// ---------------------------------------------------------------------------
export function createInitialState(startingPlayer: PlayerIndex = 0): GameState {
export function nextPlayer(playerIdx: PlayerIndex, steps = 1): PlayerIndex {
return ((playerIdx + steps) % 4) as PlayerIndex;
}
export function getOpeningPlayerForDealer(dealer: PlayerIndex): PlayerIndex {
return nextPlayer(dealer);
}
export function getDealerRelativeOrder(
dealer: PlayerIndex
): [PlayerIndex, PlayerIndex, PlayerIndex, PlayerIndex] {
const firstHand = getOpeningPlayerForDealer(dealer);
const secondHand = nextPlayer(firstHand);
const thirdHand = nextPlayer(secondHand);
return [firstHand, secondHand, thirdHand, dealer];
}
export function getDealerRelativeRole(
dealer: PlayerIndex,
playerIdx: PlayerIndex
): DealerRelativeRole {
const [firstHand, secondHand, thirdHand] = getDealerRelativeOrder(dealer);
if (playerIdx === firstHand) return 'first-hand';
if (playerIdx === secondHand) return 'second-hand';
if (playerIdx === thirdHand) return 'third-hand';
return 'dealer';
}
export function createInitialState(dealer: PlayerIndex = 3): GameState {
const deck = shuffle(buildDeck());
const startingPlayer = getOpeningPlayerForDealer(dealer);
const players: [Player, Player, Player, Player] = [
{ index: 0, hand: [], pile: [], scope: 0, isHuman: true, name: 'Tu' },
@@ -102,6 +132,7 @@ export function createInitialState(startingPlayer: PlayerIndex = 0): GameState {
players,
table,
matchStartingPlayer: startingPlayer,
dealer,
currentPlayer: startingPlayer,
roundOver: false,
gameOver: false,
@@ -164,7 +195,7 @@ export function applyMove(
}
// Advance turn
state2.currentPlayer = ((playerIdx + 1) % 4) as PlayerIndex;
state2.currentPlayer = nextPlayer(playerIdx);
// Check if round is over (all hands empty)
const allHandsEmpty = state2.players.every(p => p.hand.length === 0);
@@ -353,6 +384,7 @@ export function cloneState(state: GameState): GameState {
],
table: state.table.map(cloneCard),
matchStartingPlayer: state.matchStartingPlayer,
dealer: state.dealer,
currentPlayer: state.currentPlayer,
roundOver: state.roundOver,
gameOver: state.gameOver,