Prototype Truthtrance ally funding commitments
Verify and publish checkpoint container / container (push) Successful in 10m48s
Verify and publish checkpoint container / container (push) Successful in 10m48s
This commit is contained in:
1 parent
68643925e7
commit
c414a03a19
14 files changed
+795
-4
No files matched your search
+29
-1
@@ -23,6 +23,7 @@ import { parseRevivalExpressionClaim, revivalExpressionText, revivalExpressionPr
|
||||
import { parseLeaderRevivalClaim, leaderRevivalClaimText, leaderRevivalPromiseModeSupported, type LeaderRevivalClaim } from './leader-revival-promises';
|
||||
import { parseAllianceClaim, allianceClaimText, alliancePromiseModeSupported, type AllianceClaim } from './alliance-promises';
|
||||
import { parseBribeClaim, bribeClaimText, bribePromiseModeSupported, type BribeClaim } from './bribe-promises';
|
||||
import { parsePledgeClaim, type PledgeClaim } from './pledge-promises';
|
||||
import { parseRevivalClaim, revivalClaimText, revivalPromiseModeSupported, type RevivalClaim } from './revival-promises';
|
||||
import { parseMovementClaim, movementClaimText, movementPromiseTargetAvailable, MovementClaimError, type MovementClaim } from './movement-promises';
|
||||
import { shipmentAvailable } from './shipment-opportunity';
|
||||
@@ -112,6 +113,7 @@ export type TruthQuestion =
|
||||
| ({ kind: 'leaderRevival'; target: string } & LeaderRevivalClaim)
|
||||
| ({ kind: 'alliance'; target: string } & AllianceClaim)
|
||||
| ({ kind: 'bribe'; target: string } & BribeClaim)
|
||||
| ({ kind: 'pledgeAid'; target: string } & PledgeClaim)
|
||||
| ({ kind: 'revival'; target: string } & RevivalClaim)
|
||||
| ({ kind: 'bid'; target: string } & BidClaim)
|
||||
| ({ kind: 'phaseBid'; target: string } & PhaseBidClaim)
|
||||
@@ -279,6 +281,10 @@ function parseQuestion(g: Game, asker: string, value: unknown): TruthQuestion {
|
||||
);
|
||||
// A joint planner for Charity and other future-action questions is not yet
|
||||
// available. Do not bind incompatible action obligations in the interim.
|
||||
if (v.kind !== 'pledgeAid' && v.kind !== 'fact' && !(v.kind === 'freeform' && v.scope === 'fact') &&
|
||||
g.truthHistory?.some(row => row.turn === g.turn && row.phase === g.phase && row.answer !== 'unknown' &&
|
||||
row.question.kind === 'pledgeAid'))
|
||||
throw new TruthError('Other future-action questions are unavailable in a phase with an ally-funding answer.');
|
||||
if (v.kind !== 'charity' && v.kind !== 'fact' && v.kind !== 'freeform' &&
|
||||
g.charityPromises?.length && liveCharityPromises(g.charityPromises,v.target as string,g.turn).length)
|
||||
throw new TruthError('Finish this player’s current Charity answer before binding another action question.');
|
||||
@@ -369,6 +375,16 @@ function parseQuestion(g: Game, asker: string, value: unknown): TruthQuestion {
|
||||
'Choose current-turn ordinary bribe statements to non-allied participants in a supported table.');
|
||||
return { kind: 'bribeExpression', target: v.target, ...claim };
|
||||
}
|
||||
if (v.kind === 'pledgeAid') {
|
||||
check(Object.keys(v).sort().join(',') === 'ally,kind,minimum,phase,target,turn',
|
||||
'Supply the current phase, respondent, ally and funding minimum.');
|
||||
const claim = parsePledgeClaim(v), respondent = g.players.find(player => player.id === v.target)!;
|
||||
check(g.status === 'playing' && !g.advanced && claim.turn === g.turn && claim.phase === g.phase &&
|
||||
respondent.ally === claim.ally && g.players.some(player => player.id === claim.ally && player.ally === respondent.id) &&
|
||||
!g.response && !g.decision && !g.phaseOpening && !g.pendingTreacheryDiscard && !g.pendingKarama,
|
||||
'Choose a current mutual ally in a supported quiet Basic Bidding or Shipment and Movement window.');
|
||||
return {kind: 'pledgeAid', target: v.target, ...claim};
|
||||
}
|
||||
if (v.kind === 'bribe') {
|
||||
check(Object.keys(v).sort().join(',') === 'kind,minimum,recipient,target,turn',
|
||||
'Supply the current turn, named bribe recipient, minimum and respondent.');
|
||||
@@ -711,7 +727,8 @@ export function validateSavedTruthtrance(g: Game) {
|
||||
}
|
||||
if (window?.question?.kind === 'fact' || window?.question?.kind === 'movement' ||
|
||||
window?.question?.kind === 'freeform' && window.question.interpreted ||
|
||||
window?.question?.kind === 'traitorCall' || window?.question?.kind === 'futureBattleLeader') {
|
||||
window?.question?.kind === 'traitorCall' || window?.question?.kind === 'futureBattleLeader' ||
|
||||
window?.question?.kind === 'pledgeAid') {
|
||||
check((window.stage === 'answer' || window.stage === 'unknown') && window.queue.length > 0,
|
||||
'The saved fact question must retain its asking player and answer stage.');
|
||||
check(JSON.stringify(parseQuestion(g, window.queue[0].player, window.question)) === JSON.stringify(window.question),
|
||||
@@ -825,6 +842,7 @@ export function truthQuestionText(
|
||||
if (q.kind === 'alliance') return `Will you ${allianceClaimText(q, playerName)}?`;
|
||||
if (q.kind === 'bribeExpression') return `Will you ${bribeExpressionText(q.claim, playerName)} from now until this turn ends?`;
|
||||
if (q.kind === 'bribe') return `Will you ${bribeClaimText(q, playerName)}?`;
|
||||
if (q.kind === 'pledgeAid') return `Will you update funding available to ${playerName(q.ally)} to at least ${q.minimum} spice during this phase?`;
|
||||
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)}?`;
|
||||
@@ -955,6 +973,8 @@ export function resolveTruthAction(
|
||||
bindBribeExpression?: (g: Game, p: Player, claim: BribeExpressionClaim, answer: boolean, asker: string) => void;
|
||||
bribeAnswers?: (g: Game, p: Player, claim: BribeClaim) => TruthAnswer[];
|
||||
bindBribe?: (g: Game, p: Player, claim: BribeClaim, answer: boolean, asker: string) => void;
|
||||
pledgeAnswers?: (g: Game, p: Player, claim: PledgeClaim) => TruthAnswer[];
|
||||
bindPledge?: (g: Game, p: Player, claim: PledgeClaim, answer: boolean, asker: string) => void;
|
||||
mixedRevivalAnswers?: (g: Game, p: Player, claim: MixedRevivalClaim) => TruthAnswer[];
|
||||
bindMixedRevival?: (g: Game, p: Player, claim: MixedRevivalClaim, answer: boolean, asker: string) => void;
|
||||
revivalExpressionAnswers?: (g: Game, p: Player, claim: RevivalExpressionClaim) => TruthAnswer[];
|
||||
@@ -1161,6 +1181,9 @@ export function resolveTruthAction(
|
||||
if (w.question.kind === 'bribeExpression')
|
||||
check(effects.bribeExpressionAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a whole bribe expression compatible with earlier answers.');
|
||||
if (w.question.kind === 'pledgeAid')
|
||||
check(effects.pledgeAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a supported ally-funding question compatible with current commitments.');
|
||||
if (w.question.kind === 'bribe')
|
||||
check(effects.bribeAnswers?.(g, g.players.find(other => other.id === w.question!.target)!, w.question).length,
|
||||
'Choose a current bribe question compatible with earlier answers.');
|
||||
@@ -1295,6 +1318,11 @@ export function resolveTruthAction(
|
||||
'Choose a whole bribe answer consistent with actual funding and earlier promises.');
|
||||
if (a.answer !== 'unknown') effects.bindBribeExpression(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'pledgeAid') {
|
||||
check(effects.pledgeAnswers && effects.bindPledge && effects.pledgeAnswers(g, p, q).includes(a.answer),
|
||||
'Choose an answer consistent with current ally-funding legality.');
|
||||
if (a.answer !== 'unknown') effects.bindPledge(g, p, q, a.answer === 'yes', current.player);
|
||||
}
|
||||
if (q.kind === 'bribe') {
|
||||
check(effects.bribeAnswers && effects.bindBribe && effects.bribeAnswers(g, p, q).includes(a.answer),
|
||||
'Choose an answer consistent with actual ordinary bribe funding and earlier promises.');
|
||||
|
||||
Reference in new issue
Block a user