feat: implement diplomacy system with state management and processing logic
This commit is contained in:
@@ -95,6 +95,7 @@ export interface TurnEngineDiplomacyRow {
|
||||
destNationId: number;
|
||||
stateCode: number;
|
||||
term: number;
|
||||
meta: JsonValue;
|
||||
}
|
||||
|
||||
export interface TurnEngineTroopRow {
|
||||
@@ -307,6 +308,12 @@ export interface TurnEngineDiplomacyCreateManyInput {
|
||||
meta: InputJsonValue;
|
||||
}
|
||||
|
||||
export interface TurnEngineDiplomacyUpdateInput {
|
||||
stateCode: number;
|
||||
term: number;
|
||||
meta: InputJsonValue;
|
||||
}
|
||||
|
||||
export interface TurnEngineEventCreateManyInput {
|
||||
targetCode: string;
|
||||
priority: number;
|
||||
@@ -379,6 +386,10 @@ export interface TurnEngineDatabaseClient {
|
||||
createMany(args: {
|
||||
data: TurnEngineDiplomacyCreateManyInput[];
|
||||
}): Promise<unknown>;
|
||||
update(args: {
|
||||
where: { srcNationId: number; destNationId: number };
|
||||
data: TurnEngineDiplomacyUpdateInput;
|
||||
}): Promise<unknown>;
|
||||
deleteMany(args?: unknown): Promise<unknown>;
|
||||
};
|
||||
troop: {
|
||||
|
||||
@@ -76,6 +76,19 @@ export interface NationPatchEffect {
|
||||
targetId?: NationId;
|
||||
}
|
||||
|
||||
export interface DiplomacyPatchEffect {
|
||||
type: 'diplomacy:patch';
|
||||
srcNationId: NationId;
|
||||
destNationId: NationId;
|
||||
patch: {
|
||||
state?: number;
|
||||
term?: number;
|
||||
dead?: number;
|
||||
deadDelta?: number;
|
||||
meta?: Record<string, unknown>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface LogEffect {
|
||||
type: 'log';
|
||||
entry: LogEntryDraft;
|
||||
@@ -93,6 +106,7 @@ export type GeneralActionEffect<
|
||||
| GeneralAddEffect<TriggerState>
|
||||
| CityPatchEffect
|
||||
| NationPatchEffect
|
||||
| DiplomacyPatchEffect
|
||||
| LogEffect
|
||||
| NextTurnOverrideEffect;
|
||||
|
||||
@@ -176,6 +190,17 @@ export const createNationPatchEffect = (
|
||||
...(targetId !== undefined ? { targetId } : {}),
|
||||
});
|
||||
|
||||
export const createDiplomacyPatchEffect = (
|
||||
srcNationId: NationId,
|
||||
destNationId: NationId,
|
||||
patch: DiplomacyPatchEffect['patch']
|
||||
): DiplomacyPatchEffect => ({
|
||||
type: 'diplomacy:patch',
|
||||
srcNationId,
|
||||
destNationId,
|
||||
patch,
|
||||
});
|
||||
|
||||
export const createLogEffect = (
|
||||
message: string,
|
||||
options: Partial<Omit<LogEntryDraft, 'text'>> = {}
|
||||
@@ -224,6 +249,7 @@ export const resolveGeneralAction = <
|
||||
nations: [],
|
||||
};
|
||||
|
||||
const pendingEffects: GeneralActionEffect[] = [];
|
||||
const [nextWorld, worldPatches] = produceWithPatches(
|
||||
{
|
||||
general: context.general,
|
||||
@@ -296,6 +322,9 @@ export const resolveGeneralAction = <
|
||||
case 'general:add':
|
||||
createdGenerals.push(effect.general as General);
|
||||
break;
|
||||
case 'diplomacy:patch':
|
||||
pendingEffects.push(effect);
|
||||
break;
|
||||
case 'general:patch':
|
||||
case 'city:patch':
|
||||
case 'nation:patch':
|
||||
@@ -359,7 +388,7 @@ export const resolveGeneralAction = <
|
||||
nation: nextWorld.nation as Nation | null,
|
||||
nextTurnAt,
|
||||
logs,
|
||||
effects: [], // 이제 effects는 직접 사용되지 않음 (이미 반영됨)
|
||||
effects: pendingEffects,
|
||||
};
|
||||
if (nextWorld.city) {
|
||||
resolution.city = nextWorld.city as City;
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { GeneralTriggerState } from '../../../domain/entities.js';
|
||||
import type { Constraint, ConstraintContext } from '../../../constraints/types.js';
|
||||
import {
|
||||
beChief,
|
||||
disallowDiplomacyBetweenStatus,
|
||||
existsDestNation,
|
||||
notBeNeutral,
|
||||
occupiedCity,
|
||||
@@ -12,7 +13,7 @@ import type {
|
||||
GeneralActionOutcome,
|
||||
GeneralActionResolveContext,
|
||||
} from '../../engine.js';
|
||||
import { createLogEffect } from '../../engine.js';
|
||||
import { createDiplomacyPatchEffect, createLogEffect } from '../../engine.js';
|
||||
import { LogCategory, LogFormat, LogScope } from '../../../logging/types.js';
|
||||
import type { TurnCommandEnv } from '../commandEnv.js';
|
||||
import type { NationTurnCommandSpec } from './index.js';
|
||||
@@ -22,6 +23,9 @@ export interface DeclareWarArgs {
|
||||
}
|
||||
|
||||
const ACTION_NAME = '선전포고';
|
||||
// legacy 규칙: 선전포고 상태는 24턴 유지.
|
||||
const DIPLOMACY_DECLARE = 1;
|
||||
const DECLARE_TERM = 24;
|
||||
|
||||
const parseNationId = (raw: unknown): number | null => {
|
||||
if (typeof raw !== 'number' || !Number.isFinite(raw)) {
|
||||
@@ -52,18 +56,45 @@ export class ActionDefinition<
|
||||
suppliedCity(),
|
||||
beChief(),
|
||||
existsDestNation(),
|
||||
disallowDiplomacyBetweenStatus({
|
||||
0: '아국과 이미 교전중입니다.',
|
||||
1: '아국과 이미 선포중입니다.',
|
||||
7: '불가침국입니다.',
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
resolve(
|
||||
_context: GeneralActionResolveContext<TriggerState>,
|
||||
context: GeneralActionResolveContext<TriggerState>,
|
||||
args: DeclareWarArgs
|
||||
): GeneralActionOutcome<TriggerState> {
|
||||
void _context;
|
||||
const nationId = context.nation?.id;
|
||||
if (nationId === undefined || nationId <= 0) {
|
||||
return {
|
||||
effects: [
|
||||
createLogEffect(
|
||||
`${ACTION_NAME}을 준비했지만 국가 정보가 없습니다.`,
|
||||
{
|
||||
scope: LogScope.GENERAL,
|
||||
category: LogCategory.ACTION,
|
||||
format: LogFormat.MONTH,
|
||||
}
|
||||
),
|
||||
],
|
||||
};
|
||||
}
|
||||
return {
|
||||
effects: [
|
||||
createDiplomacyPatchEffect(nationId, args.destNationId, {
|
||||
state: DIPLOMACY_DECLARE,
|
||||
term: DECLARE_TERM,
|
||||
}),
|
||||
createDiplomacyPatchEffect(args.destNationId, nationId, {
|
||||
state: DIPLOMACY_DECLARE,
|
||||
term: DECLARE_TERM,
|
||||
}),
|
||||
createLogEffect(
|
||||
`${ACTION_NAME}을 준비했습니다. (국가 ${args.destNationId})`,
|
||||
`${ACTION_NAME}을 실행했습니다. (국가 ${args.destNationId})`,
|
||||
{
|
||||
scope: LogScope.GENERAL,
|
||||
category: LogCategory.ACTION,
|
||||
|
||||
Reference in New Issue
Block a user