feat(SCOPONE-0009) improve ai, dealer, apparigliare e sparigliare

This commit is contained in:
Giancarmine Salucci
2026-04-09 22:30:27 +02:00
parent d0a44d295a
commit 77ab1f43a6
8 changed files with 3787 additions and 510 deletions

View File

@@ -4,19 +4,19 @@ export interface CardTrackerSnapshot {
playedCardIds: string[];
}
export interface CardTrackerValueParityResidue {
export interface CardTrackerValueRankResidue {
value: number;
knownCount: number;
unseenCount: number;
hasOddUnseenResidue: boolean;
hasEvenUnseenResidue: boolean;
hasSingletonUnseenRankResidue: boolean;
hasPairedUnseenRankResidue: boolean;
}
interface VisibleValueResidueKnowledge {
unseenCards: Card[];
unseenCountBySuit: Record<Suit, number>;
unseenCountByValue: number[];
valueParityResidues: CardTrackerValueParityResidue[];
valueRankResidues: CardTrackerValueRankResidue[];
}
function normalizeSnapshot(snapshot: CardTrackerSnapshot): CardTrackerSnapshot {
@@ -116,15 +116,15 @@ export class CardTracker {
}
}
const valueParityResidues: CardTrackerValueParityResidue[] = [];
const valueRankResidues: CardTrackerValueRankResidue[] = [];
for (let value = 1; value <= 10; value++) {
const unseenCount = unseenCountByValue[value];
valueParityResidues.push({
valueRankResidues.push({
value,
knownCount: knownCountByValue[value],
unseenCount,
hasOddUnseenResidue: unseenCount % 2 === 1,
hasEvenUnseenResidue: unseenCount % 2 === 0,
hasSingletonUnseenRankResidue: unseenCount % 2 === 1,
hasPairedUnseenRankResidue: unseenCount >= 2 && unseenCount % 2 === 0,
});
}
@@ -132,7 +132,7 @@ export class CardTracker {
unseenCards,
unseenCountBySuit,
unseenCountByValue,
valueParityResidues,
valueRankResidues,
};
}
@@ -151,24 +151,24 @@ export class CardTracker {
/** Count how many unseen cards share a value */
countRemainingValue(value: number, myHand: Card[], table: Card[]): number {
return this.getValueParityResidue(value, myHand, table).unseenCount;
return this.getValueRankResidue(value, myHand, table).unseenCount;
}
/** Get visible known-count, unseen-count, and parity residue for a single value */
getValueParityResidue(value: number, myHand: Card[], table: Card[]): CardTrackerValueParityResidue {
const valueParityResidues = this.buildVisibleValueResidueKnowledge(myHand, table).valueParityResidues;
return valueParityResidues[value - 1] ?? {
/** Get visible known-count, unseen-count, and same-rank residue for a single value */
getValueRankResidue(value: number, myHand: Card[], table: Card[]): CardTrackerValueRankResidue {
const valueRankResidues = this.buildVisibleValueResidueKnowledge(myHand, table).valueRankResidues;
return valueRankResidues[value - 1] ?? {
value,
knownCount: 0,
unseenCount: 0,
hasOddUnseenResidue: false,
hasEvenUnseenResidue: true,
hasSingletonUnseenRankResidue: false,
hasPairedUnseenRankResidue: false,
};
}
/** Get visible known-count, unseen-count, and parity residue for all card values */
getValueParityResidueSummary(myHand: Card[], table: Card[]): CardTrackerValueParityResidue[] {
return this.buildVisibleValueResidueKnowledge(myHand, table).valueParityResidues;
/** Get visible known-count, unseen-count, and same-rank residue for all card values */
getValueRankResidueSummary(myHand: Card[], table: Card[]): CardTrackerValueRankResidue[] {
return this.buildVisibleValueResidueKnowledge(myHand, table).valueRankResidues;
}
/** Probability that a hidden hand contains at least one card with the requested value */