Combine current-turn payments with shipment and movement promises
This commit is contained in:
1 parent
8dbec05844
commit
0d72a33ee5
18 files changed
+2591
-7
No files matched your search
@@ -1,4 +1,6 @@
|
||||
import { parseTravelActionClaim, type TravelClaim } from './travel-expression-promises';
|
||||
import { parseTurnActionLeaf, TURN_ACTION_MAX_DEPTH, TURN_ACTION_MAX_LEAVES,
|
||||
type TurnActionClaim } from './turn-action-promises';
|
||||
import { parseTraitorActionClaim, type MixedTraitorClaim } from './mixed-traitor-question';
|
||||
import { parseBattleActionClaim, MIXED_BATTLE_MAX_NODES, MIXED_BATTLE_MAX_TERMS, MIXED_BATTLE_MAX_DEPTH,
|
||||
MIXED_BATTLE_MAX_LEAVES, type MixedBattleClaim } from './mixed-battle-question';
|
||||
@@ -79,6 +81,7 @@ export type TruthFact =
|
||||
| { kind: 'and' | 'or'; terms: TruthFact[] };
|
||||
export type MixedMovementClaim = { turn: number; mixed: MixedActionExpression<MovementClaim> };
|
||||
export type TruthQuestion =
|
||||
| ({ kind: 'turnActions'; target: string } & TurnActionClaim)
|
||||
| ({ kind: 'travel'; target: string } & TravelClaim)
|
||||
| ({ kind: 'mixedTraitorCall'; target: string } & MixedTraitorClaim)
|
||||
| ({ kind: 'mixedBattlePlan'; target: string } & MixedBattleClaim)
|
||||
@@ -372,6 +375,20 @@ function parseQuestion(g: Game, asker: string, value: unknown): TruthQuestion {
|
||||
'Choose the current ordinary bid lot in a supported table and finish pending decisions.');
|
||||
return { kind: 'bid', target: v.target, ...claim };
|
||||
}
|
||||
if (v.kind === 'turnActions') {
|
||||
check(Object.keys(v).sort().join(',') === 'kind,mixed,target,turn' && v.turn === g.turn &&
|
||||
bribePromiseModeSupported(g) && g.status === 'playing' && Number.isInteger(g.phase) && g.phase >= 0 && g.phase <= 8 &&
|
||||
!g.response && !g.decision && !g.phaseOpening && !g.pendingTreacheryDiscard && !g.pendingKarama,
|
||||
'Supply the current turn, complete turn-action question and a supported quiet native window.');
|
||||
const respondent = g.players.find(player => player.id === v.target)!;
|
||||
const mixed = parseMixedActionExpression(v.mixed, fact => parseFact(g, fact, respondent), input => {
|
||||
const action = parseTurnActionLeaf(input);
|
||||
if (action.kind === 'payment') check(action.recipient !== respondent.id && action.recipient !== respondent.ally &&
|
||||
g.players.some(player => player.id === action.recipient), 'Choose another current non-allied ordinary bribe recipient.');
|
||||
return action;
|
||||
}, { requireFact: false, maxDepth: TURN_ACTION_MAX_DEPTH, maxLeaves: TURN_ACTION_MAX_LEAVES });
|
||||
return { kind: 'turnActions', target: v.target as string, turn: g.turn, mixed };
|
||||
}
|
||||
if (v.kind === 'travel') {
|
||||
check(Object.keys(v).sort().join(',') === 'kind,mixed,target,turn' && g.status === 'playing' &&
|
||||
Number.isInteger(g.phase) && g.phase >= 0 && g.phase <= 5 && v.turn === g.turn,
|
||||
@@ -681,6 +698,9 @@ export function truthQuestionText(
|
||||
return `you currently hold ${f.compare === 'eq' ? 'exactly' : f.compare === 'gte' ? 'at least' : 'at most'} ${f.value} spice`;
|
||||
return `(${f.terms.map(clause).join(f.kind === 'and' ? ' AND ' : ' OR ')})`;
|
||||
};
|
||||
if (q.kind === 'turnActions') return `Is it true that ${mixedActionExpressionText(q.mixed, clause,
|
||||
action => action.kind === 'payment' ? `you ${bribeClaimText({ turn: q.turn, ...action }, playerName)}` :
|
||||
`you ${action.kind === 'ship' ? shipmentClaimText(action) : movementClaimText(action)} before your Shipment and Movement turn ends`)}?`;
|
||||
if (q.kind === 'travel') return `Is it true that ${mixedActionExpressionText(q.mixed, clause,
|
||||
action => `you ${action.kind === 'ship' ? shipmentClaimText(action) : movementClaimText(action)}`)} this turn?`;
|
||||
if (q.kind === 'mixedTraitorCall') return `Is it true that ${mixedActionExpressionText(q.mixed, clause,
|
||||
@@ -754,6 +774,8 @@ export function resolveTruthAction(
|
||||
bindBid?: (g: Game, p: Player, claim: BidClaim, 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[];
|
||||
bindTurnAction?: (g: Game, p: Player, claim: TurnActionClaim, answer: boolean, asker: string) => void;
|
||||
mixedTraitorAnswers?: (g: Game, p: Player, claim: MixedTraitorClaim) => TruthAnswer[];
|
||||
bindMixedTraitor?: (g: Game, p: Player, claim: MixedTraitorClaim, answer: boolean, asker: string) => void;
|
||||
traitorAnswers?: (g: Game, p: Player) => TruthAnswer[];
|
||||
@@ -924,6 +946,9 @@ export function resolveTruthAction(
|
||||
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.');
|
||||
if (w.question.kind === 'turnActions')
|
||||
check(effects.turnActionAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a whole turn-action question compatible with native opportunities and earlier answers.');
|
||||
if (w.question.kind === 'mixedTraitorCall')
|
||||
check(effects.mixedTraitorAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a whole mixed Traitor question for an actual current voter.');
|
||||
@@ -1053,6 +1078,11 @@ export function resolveTruthAction(
|
||||
'Choose a whole travel answer compatible with native actions and earlier commitments.');
|
||||
if (a.answer !== 'unknown') effects.bindTravel(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'turnActions') {
|
||||
check(effects.turnActionAnswers && effects.bindTurnAction && effects.turnActionAnswers(g, p, q).includes(a.answer),
|
||||
'Choose a whole turn-action answer compatible with current facts, native actions and earlier commitments.');
|
||||
if (a.answer !== 'unknown') effects.bindTurnAction(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'mixedTraitorCall') {
|
||||
check(effects.mixedTraitorAnswers && effects.bindMixedTraitor && effects.mixedTraitorAnswers(g, p, q).includes(a.answer),
|
||||
'Choose an aggregate answer compatible with this mixed question and current native declaration.');
|
||||
|
||||
Reference in new issue
Block a user