Support phase-wide Truthtrance bid commitments
This commit is contained in:
1 parent
474674f7fe
commit
2916b4d48f
19 files changed
+1512
-15
No files matched your search
@@ -70,6 +70,7 @@ import { isKnowledgeFact, parseKnowledgeFact, knowledgeFactAnswer, knowledgeFact
|
||||
import { parseNoFieldValueFact, noFieldValueFactMatches, noFieldValueFactText, type NoFieldValueFact } from './truthtrance-no-field-value';
|
||||
import { parseFaceDancerFact, faceDancerFactMatches, faceDancerFactText, type FaceDancerFact } from './truthtrance-face-dancer';
|
||||
import { parseBidClaim, bidClaimText, bidPromiseModeSupported, type BidClaim } from './bid-promises';
|
||||
import { parsePhaseBidClaim, phaseBidClaimText, phaseBidPromiseModeSupported, type PhaseBidClaim } from './turn-bid-promises';
|
||||
|
||||
export type TruthFact =
|
||||
| KnowledgeFact
|
||||
@@ -102,6 +103,7 @@ export type TruthQuestion =
|
||||
| ({ kind: 'bribe'; target: string } & BribeClaim)
|
||||
| ({ kind: 'revival'; target: string } & RevivalClaim)
|
||||
| ({ kind: 'bid'; target: string } & BidClaim)
|
||||
| ({ kind: 'phaseBid'; target: string } & PhaseBidClaim)
|
||||
| { kind: 'traitorCall'; target: string; battle: string; territory: string }
|
||||
| ({ kind: 'movement'; target: string } & MovementClaim)
|
||||
| ({ kind: 'shipment'; target: string } & ShipmentClaim)
|
||||
@@ -354,6 +356,18 @@ function parseQuestion(g: Game, asker: string, value: unknown): TruthQuestion {
|
||||
'Choose a remaining native Revival opportunity this turn in a supported table and finish pending decisions.');
|
||||
return { kind: 'revival', target: v.target, ...claim };
|
||||
}
|
||||
if (v.kind === 'phaseBid') {
|
||||
check(Object.keys(v).sort().join(',') === 'kind,minimum,target,turn',
|
||||
'Supply the current turn, phase bid minimum and respondent.');
|
||||
const claim = parsePhaseBidClaim(v);
|
||||
check(phaseBidPromiseModeSupported(g) && g.status === 'playing' && Number.isInteger(g.phase) &&
|
||||
g.phase >= 0 && g.phase <= 3 && claim.turn === g.turn &&
|
||||
(g.phase < 3 || !!g.auction && !g.currentAuctionSale && !g.richeseAuction && !g.ixAuction) &&
|
||||
!g.response && !g.decision && !g.phaseOpening && !g.pendingRevival &&
|
||||
!g.pendingKarama && !g.pendingTreacheryDiscard,
|
||||
'Choose the current turn and a quiet supported ordinary Bidding opportunity.');
|
||||
return { kind: 'phaseBid', target: v.target, ...claim };
|
||||
}
|
||||
if (v.kind === 'mixedBid') {
|
||||
check(Object.keys(v).sort().join(',') === 'kind,lot,mixed,target,turn',
|
||||
'Supply the current ordinary lot, turn, complete mixed bid question and respondent.');
|
||||
@@ -718,6 +732,7 @@ export function truthQuestionText(
|
||||
if (q.kind === 'bribe') return `Will you ${bribeClaimText(q, playerName)}?`;
|
||||
if (q.kind === 'revival') return `Will you ${revivalClaimText(q)}?`;
|
||||
if (q.kind === 'bid') return `Will you ${bidClaimText(q)}?`;
|
||||
if (q.kind === 'phaseBid') return `Will you ${phaseBidClaimText(q)}?`;
|
||||
if (q.kind === 'traitorCall') return `In this revealed battle in ${locationName(q.territory)}, will you declare the opposing leader a Traitor?`;
|
||||
if (q.kind === 'movementExpression') return `Will you ${movementExpressionText(q.claim)} before your Shipment and Movement turn ends?`;
|
||||
if (q.kind === 'movement') return `Will you ${movementClaimText(q)} before your Shipment and Movement turn ends?`;
|
||||
@@ -848,6 +863,8 @@ export function resolveTruthAction(
|
||||
bindMixedBid?: (g: Game, p: Player, claim: MixedBidClaim, answer: boolean, asker: string) => void;
|
||||
bidAnswers?: (g: Game, p: Player, claim: BidClaim) => TruthAnswer[];
|
||||
bindBid?: (g: Game, p: Player, claim: BidClaim, answer: boolean, asker: string) => void;
|
||||
phaseBidAnswers?: (g: Game, p: Player, claim: PhaseBidClaim) => TruthAnswer[];
|
||||
bindPhaseBid?: (g: Game, p: Player, claim: PhaseBidClaim, answer: boolean, asker: string) => void;
|
||||
travelAnswers?: (g: Game, p: Player, claim: TravelClaim) => TruthAnswer[];
|
||||
bindTravel?: (g: Game, p: Player, claim: TravelClaim, answer: boolean, asker: string) => void;
|
||||
turnActionAnswers?: (g: Game, p: Player, claim: TurnActionClaim) => TruthAnswer[];
|
||||
@@ -1019,6 +1036,9 @@ export function resolveTruthAction(
|
||||
if (w.question.kind === 'bid')
|
||||
check(effects.bidAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a bidder with a remaining ordinary opportunity in this lot.');
|
||||
if (w.question.kind === 'phaseBid')
|
||||
check(effects.phaseBidAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a phase bid question compatible with supported native opportunities and earlier answers.');
|
||||
if (w.question.kind === 'travel')
|
||||
check(effects.travelAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose an unused or active native Shipment and Movement opportunity.');
|
||||
@@ -1149,6 +1169,11 @@ export function resolveTruthAction(
|
||||
'Choose an answer consistent with this lot, your legal bids and earlier answers.');
|
||||
if (a.answer !== 'unknown') effects.bindBid(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'phaseBid') {
|
||||
check(effects.phaseBidAnswers && effects.bindPhaseBid && effects.phaseBidAnswers(g, p, q).includes(a.answer),
|
||||
'Choose an answer consistent with native bids and earlier phase commitments.');
|
||||
if (a.answer !== 'unknown') effects.bindPhaseBid(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'travel') {
|
||||
check(effects.travelAnswers && effects.bindTravel && effects.travelAnswers(g, p, q).includes(a.answer),
|
||||
'Choose a whole travel answer compatible with native actions and earlier commitments.');
|
||||
|
||||
Reference in new issue
Block a user