Some checks failed
Android Build & Publish / android (push) Failing after 2m10s
- 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
81 lines
1.7 KiB
TypeScript
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[];
|
|
}
|