Files
scopone/src/game/types.ts
Giancarmine Salucci 3f74c57665
Some checks failed
Android Build & Publish / android (push) Failing after 2m10s
feat(SCOPONE-0013): PIMC AI rewrite + Gitea Android CI pipeline
- Replace minimax with PIMC (Perfect Information Monte Carlo) search
- Add PIMC_SCOPE_BOOST=150 → effective scopa value 540 (was 390)
  → Master win rate: 67.5% → 72.5% vs legacy AI (target ≥60%)
  → Advanced win rate: 97.5% vs beginner AI (target ≥55%)
  → Scope gap in losses: 6.54 → 3.00 scopa/match
- Add card inference engine for probabilistic hand tracking
- Add ai-strategy, ai-legacy evaluation bridge
- Add .gitea/workflows/android-build.yml: build debug + unsigned
  release APK and publish to Gitea generic package registry
2026-05-24 16:29:04 +02:00

81 lines
1.7 KiB
TypeScript

export type Suit = 'bastoni' | 'coppe' | 'denara' | 'spade';
export const SUITS: Suit[] = ['bastoni', 'coppe', 'denara', 'spade'];
export interface Card {
suit: Suit;
value: number; // 1-10
id: string; // e.g. "denara_7"
}
export interface Capture {
played: Card;
captured: Card[];
}
export type PlayerIndex = 0 | 1 | 2 | 3;
export type DealerRelativeRole = 'first-hand' | 'second-hand' | 'third-hand' | 'dealer';
export type Difficulty = 'beginner' | 'advanced' | 'master';
export interface Player {
index: PlayerIndex;
hand: Card[];
pile: Card[]; // captured cards
scope: number; // number of scope achieved
isHuman: boolean;
name: string;
}
export interface GameState {
players: [Player, Player, Player, Player];
table: Card[];
matchStartingPlayer: PlayerIndex;
dealer: PlayerIndex;
currentPlayer: PlayerIndex;
roundOver: boolean;
gameOver: boolean;
teamScores: [TeamScore, TeamScore]; // Team 0: players 0+2, Team 1: players 1+3
lastCapturTeam: 0 | 1 | null; // which team made the last capture (gets remaining table cards)
roundNumber: number;
}
export interface TeamScore {
cards: number;
scope: number;
denari: number;
settebello: boolean;
primiera: number;
// final points for this round
roundPoints: number;
totalPoints: number;
}
export interface ScoreBreakdown {
cartePoint: 0 | 1 | null; // null = tie
denariPoint: 0 | 1 | null;
settebelloPoint: 0 | 1;
primieraPoint: 0 | 1 | null;
scopeTeam0: number;
scopeTeam1: number;
}
// Primiera values per card value
export const PRIMIERA_VALUES: Record<number, number> = {
7: 21,
6: 18,
1: 16,
5: 15,
4: 14,
3: 13,
2: 12,
8: 10,
9: 10,
10: 10,
};
export interface AIMove {
card: Card;
capture: Card[];
}