batched round: queue actions/diplomacy, jump forward commits one turn (v0.2.0)
CI / build + unit + e2e (pull_request) Successful in 1m51s
CI / build + unit + e2e (pull_request) Successful in 1m51s
This commit is contained in:
+35
-30
@@ -2,11 +2,12 @@
|
||||
// sets LLM_STUB=1) so the whole loop is reproducible with no live model. It
|
||||
// speaks the OpenAI chat-completions wire shape, so it plugs in as a Transport.
|
||||
import { createLlmClient, type ChatMessage, type Transport } from './llm';
|
||||
import { addDays, clampStat, type TurnResult } from '../shared/protocol';
|
||||
import { addDays, clampStat, type TurnEventSpec, type TurnResult } from '../shared/protocol';
|
||||
import type { RoundItem } from '../shared/types';
|
||||
|
||||
export const ADVISOR_MARKER = '<<ADVISOR>>';
|
||||
|
||||
/** The parsed body of the user message the engine sends (see engine.buildPrompt). */
|
||||
/** The parsed body of the user message the engine sends (see engine.buildUserPrompt). */
|
||||
export interface StubPayload {
|
||||
state?: {
|
||||
turn: number;
|
||||
@@ -14,8 +15,8 @@ export interface StubPayload {
|
||||
playerNationId: string;
|
||||
nations: Record<string, { stats: Record<string, number> }>;
|
||||
};
|
||||
action?: string | null;
|
||||
chat?: { to: string; message: string } | null;
|
||||
/** The raw pending round the engine emitted (one entry per queued item). */
|
||||
pending?: RoundItem[];
|
||||
}
|
||||
|
||||
function truncate(s: string, n: number): string {
|
||||
@@ -24,8 +25,12 @@ function truncate(s: string, n: number): string {
|
||||
|
||||
/**
|
||||
* Pure deterministic TurnResult for a parsed payload. Bumps the player nation's
|
||||
* military by 5 each turn (clamped to 0–100) and emits one event, so a caller can
|
||||
* predict the exact next state for assertions.
|
||||
* military by 5 each turn (clamped to 0–100) and emits one event per queued
|
||||
* round item (action → military/success, diplomacy → diplomatic/partial), or a
|
||||
* single political "The world moves on" event when the round is empty — so a
|
||||
* caller can predict the exact next state for assertions. It always sets the
|
||||
* player's military to (current + 5) and allies the player with the first other
|
||||
* nation, advancing the date by 2 days.
|
||||
*/
|
||||
export function deterministicTurn(p: StubPayload): TurnResult {
|
||||
const state = p.state;
|
||||
@@ -35,36 +40,36 @@ export function deterministicTurn(p: StubPayload): TurnResult {
|
||||
const otherId = state
|
||||
? (Object.keys(state.nations).find((id) => id !== pid) ?? '')
|
||||
: 'us';
|
||||
const items = p.pending ?? [];
|
||||
|
||||
const events = p.action
|
||||
? [
|
||||
{
|
||||
nation: pid,
|
||||
type: 'military' as const,
|
||||
title: `Action: ${truncate(p.action, 60)}`,
|
||||
text: 'Your move takes effect across the region.',
|
||||
outcome: 'success' as const,
|
||||
},
|
||||
]
|
||||
: p.chat
|
||||
const events: TurnEventSpec[] =
|
||||
items.length === 0
|
||||
? [
|
||||
{
|
||||
nation: pid,
|
||||
type: 'diplomatic' as const,
|
||||
title: 'Diplomatic outreach',
|
||||
text: 'Your message is received by the target nation.',
|
||||
outcome: 'partial' as const,
|
||||
type: 'political',
|
||||
title: 'The world moves on',
|
||||
text: 'Weeks pass without a decisive event.',
|
||||
outcome: 'neutral',
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
nation: pid,
|
||||
type: 'political' as const,
|
||||
title: 'The world moves on',
|
||||
text: 'Weeks pass; the great powers posture and rearm quietly.',
|
||||
outcome: 'neutral' as const,
|
||||
},
|
||||
];
|
||||
: items.map((it) =>
|
||||
it.kind === 'action'
|
||||
? {
|
||||
nation: pid,
|
||||
type: 'military' as const,
|
||||
title: `Action: ${truncate(it.text, 60)}`,
|
||||
text: 'Your move takes effect across the region.',
|
||||
outcome: 'success' as const,
|
||||
}
|
||||
: {
|
||||
nation: pid,
|
||||
type: 'diplomatic' as const,
|
||||
title: 'Diplomatic outreach',
|
||||
text: 'Your message is received.',
|
||||
outcome: 'partial' as const,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
date: addDays(state?.date ?? '1939-09-01', 2),
|
||||
|
||||
Reference in New Issue
Block a user