코드
This commit is contained in:
@@ -1,11 +1,6 @@
|
|||||||
import type { GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js';
|
import type { GeneralTriggerState } from '@sammo-ts/logic/domain/entities.js';
|
||||||
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
||||||
import {
|
import { mustBeNPC, reqGeneralGold, unknownOrDeny, existsDestCity } from '@sammo-ts/logic/constraints/presets.js';
|
||||||
mustBeNPC,
|
|
||||||
reqGeneralGold,
|
|
||||||
unknownOrDeny,
|
|
||||||
existsDestCity,
|
|
||||||
} from '@sammo-ts/logic/constraints/presets.js';
|
|
||||||
import type { GeneralActionDefinition } from '@sammo-ts/logic/actions/definition.js';
|
import type { GeneralActionDefinition } from '@sammo-ts/logic/actions/definition.js';
|
||||||
import type {
|
import type {
|
||||||
GeneralActionOutcome,
|
GeneralActionOutcome,
|
||||||
@@ -25,9 +20,8 @@ export interface NPCSelfArgs {
|
|||||||
destCityId?: number;
|
destCityId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NPCSelfResolveContext<
|
export type NPCSelfResolveContext<TriggerState extends GeneralTriggerState = GeneralTriggerState> =
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
GeneralActionResolveContext<TriggerState> & {
|
||||||
> = GeneralActionResolveContext<TriggerState> & {
|
|
||||||
map?: MapDefinition;
|
map?: MapDefinition;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,7 +29,7 @@ const ACTION_NAME = 'NPC능동';
|
|||||||
const ACTION_KEY = 'che_NPC능동';
|
const ACTION_KEY = 'che_NPC능동';
|
||||||
|
|
||||||
export class ActionResolver<
|
export class ActionResolver<
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||||
> implements GeneralActionResolver<TriggerState, NPCSelfArgs> {
|
> implements GeneralActionResolver<TriggerState, NPCSelfArgs> {
|
||||||
readonly key = ACTION_KEY;
|
readonly key = ACTION_KEY;
|
||||||
|
|
||||||
@@ -85,7 +79,7 @@ export class ActionResolver<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ActionDefinition<
|
export class ActionDefinition<
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||||
> implements GeneralActionDefinition<TriggerState, NPCSelfArgs, NPCSelfResolveContext<TriggerState>> {
|
> implements GeneralActionDefinition<TriggerState, NPCSelfArgs, NPCSelfResolveContext<TriggerState>> {
|
||||||
public readonly key = ACTION_KEY;
|
public readonly key = ACTION_KEY;
|
||||||
public readonly name = ACTION_NAME;
|
public readonly name = ACTION_NAME;
|
||||||
@@ -111,9 +105,7 @@ export class ActionDefinition<
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildConstraints(ctx: ConstraintContext, args: NPCSelfArgs): Constraint[] {
|
buildConstraints(ctx: ConstraintContext, args: NPCSelfArgs): Constraint[] {
|
||||||
const constraints = [
|
const constraints = [mustBeNPC()];
|
||||||
mustBeNPC()
|
|
||||||
];
|
|
||||||
|
|
||||||
if (args.optionText === '순간이동') {
|
if (args.optionText === '순간이동') {
|
||||||
constraints.push(existsDestCity());
|
constraints.push(existsDestCity());
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export interface ForcedMoveArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ForcedMoveResolveContext<
|
export interface ForcedMoveResolveContext<
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||||
> extends GeneralActionResolveContext<TriggerState> {
|
> extends GeneralActionResolveContext<TriggerState> {
|
||||||
moveGenerals?: General<TriggerState>[]; // For roaming move
|
moveGenerals?: General<TriggerState>[]; // For roaming move
|
||||||
map?: MapDefinition;
|
map?: MapDefinition;
|
||||||
@@ -39,7 +39,7 @@ const ACTION_NAME = '강행';
|
|||||||
const ACTION_KEY = 'che_강행';
|
const ACTION_KEY = 'che_강행';
|
||||||
|
|
||||||
export class ActionResolver<
|
export class ActionResolver<
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||||
> implements GeneralActionResolver<TriggerState, ForcedMoveArgs> {
|
> implements GeneralActionResolver<TriggerState, ForcedMoveArgs> {
|
||||||
readonly key = ACTION_KEY;
|
readonly key = ACTION_KEY;
|
||||||
|
|
||||||
@@ -97,7 +97,8 @@ export class ActionResolver<
|
|||||||
const nextTrain = Math.max(20, general.train - 5);
|
const nextTrain = Math.max(20, general.train - 5);
|
||||||
const nextAtmos = Math.max(20, general.atmos - 5);
|
const nextAtmos = Math.max(20, general.atmos - 5);
|
||||||
const nextExp = general.experience + 100;
|
const nextExp = general.experience + 100;
|
||||||
const nextLeadershipExp = (typeof general.meta.leadership_exp === 'number' ? general.meta.leadership_exp : 0) + 1;
|
const nextLeadershipExp =
|
||||||
|
(typeof general.meta.leadership_exp === 'number' ? general.meta.leadership_exp : 0) + 1;
|
||||||
|
|
||||||
effects.push(
|
effects.push(
|
||||||
createGeneralPatchEffect(
|
createGeneralPatchEffect(
|
||||||
@@ -135,7 +136,7 @@ export class ActionResolver<
|
|||||||
createGeneralPatchEffect(
|
createGeneralPatchEffect(
|
||||||
{
|
{
|
||||||
...target,
|
...target,
|
||||||
cityId: destCityId
|
cityId: destCityId,
|
||||||
},
|
},
|
||||||
target.id
|
target.id
|
||||||
)
|
)
|
||||||
@@ -148,7 +149,7 @@ export class ActionResolver<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ActionDefinition<
|
export class ActionDefinition<
|
||||||
TriggerState extends GeneralTriggerState = GeneralTriggerState
|
TriggerState extends GeneralTriggerState = GeneralTriggerState,
|
||||||
> implements GeneralActionDefinition<TriggerState, ForcedMoveArgs, ForcedMoveResolveContext<TriggerState>> {
|
> implements GeneralActionDefinition<TriggerState, ForcedMoveArgs, ForcedMoveResolveContext<TriggerState>> {
|
||||||
public readonly key = ACTION_KEY;
|
public readonly key = ACTION_KEY;
|
||||||
public readonly name = ACTION_NAME;
|
public readonly name = ACTION_NAME;
|
||||||
@@ -173,7 +174,7 @@ export class ActionDefinition<
|
|||||||
const cost = ctx.env.develCost as number;
|
const cost = ctx.env.develCost as number;
|
||||||
return (cost ?? 0) * 5;
|
return (cost ?? 0) * 5;
|
||||||
}),
|
}),
|
||||||
reqGeneralRice(() => 0) // Legacy checks cost[1] which is 0, but included constraint.
|
reqGeneralRice(() => 0), // Legacy checks cost[1] which is 0, but included constraint.
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import type { City, General, GeneralTriggerState, Nation } from '@sammo-ts/logic/domain/entities.js';
|
import type { City, General, GeneralTriggerState, Nation } from '@sammo-ts/logic/domain/entities.js';
|
||||||
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
||||||
import {
|
import {
|
||||||
@@ -94,7 +93,7 @@ export class ActionResolver<
|
|||||||
let foundDestCity: City | undefined;
|
let foundDestCity: City | undefined;
|
||||||
|
|
||||||
if (context.nationCities) {
|
if (context.nationCities) {
|
||||||
foundDestCity = context.nationCities.find(c => c.id === destCityId);
|
foundDestCity = context.nationCities.find((c) => c.id === destCityId);
|
||||||
if (foundDestCity) {
|
if (foundDestCity) {
|
||||||
destCityName = foundDestCity.name;
|
destCityName = foundDestCity.name;
|
||||||
}
|
}
|
||||||
@@ -116,7 +115,9 @@ export class ActionResolver<
|
|||||||
const exp = 70;
|
const exp = 70;
|
||||||
const ded = 100;
|
const ded = 100;
|
||||||
|
|
||||||
effects.push(createGeneralPatchEffect({
|
effects.push(
|
||||||
|
createGeneralPatchEffect(
|
||||||
|
{
|
||||||
...general,
|
...general,
|
||||||
cityId: destCityId,
|
cityId: destCityId,
|
||||||
experience: general.experience + exp,
|
experience: general.experience + exp,
|
||||||
@@ -134,9 +135,12 @@ export class ActionResolver<
|
|||||||
// Default to meta if needed.
|
// Default to meta if needed.
|
||||||
meta: {
|
meta: {
|
||||||
...general.meta,
|
...general.meta,
|
||||||
leadership_exp: (readMetaNumberFromUnknown(general.meta, 'leadership_exp') ?? 0) + 1
|
leadership_exp: (readMetaNumberFromUnknown(general.meta, 'leadership_exp') ?? 0) + 1,
|
||||||
}
|
},
|
||||||
}, general.id));
|
},
|
||||||
|
general.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return { effects };
|
return { effects };
|
||||||
}
|
}
|
||||||
@@ -175,7 +179,7 @@ export const actionContextBuilder: ActionContextBuilder = (base, options) => {
|
|||||||
...base,
|
...base,
|
||||||
// We effectively need all cities to find the destination name if it's not the capital.
|
// We effectively need all cities to find the destination name if it's not the capital.
|
||||||
// Or at least nation cities.
|
// Or at least nation cities.
|
||||||
nationCities: options.worldRef?.listCities().filter(c => c.nationId === base.nation?.id) ?? [],
|
nationCities: options.worldRef?.listCities().filter((c) => c.nationId === base.nation?.id) ?? [],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import type { General, GeneralTriggerState, Nation } from '@sammo-ts/logic/domain/entities.js';
|
import type { General, GeneralTriggerState, Nation } from '@sammo-ts/logic/domain/entities.js';
|
||||||
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
import type { Constraint, ConstraintContext } from '@sammo-ts/logic/constraints/types.js';
|
||||||
import {
|
import {
|
||||||
@@ -45,7 +44,10 @@ export class ActionResolver<
|
|||||||
> implements GeneralActionResolver<TriggerState, AcceptScoutArgs> {
|
> implements GeneralActionResolver<TriggerState, AcceptScoutArgs> {
|
||||||
readonly key = ACTION_KEY;
|
readonly key = ACTION_KEY;
|
||||||
|
|
||||||
resolve(context: AcceptScoutResolveContext<TriggerState>, _args: AcceptScoutArgs): GeneralActionOutcome<TriggerState> {
|
resolve(
|
||||||
|
context: AcceptScoutResolveContext<TriggerState>,
|
||||||
|
_args: AcceptScoutArgs
|
||||||
|
): GeneralActionOutcome<TriggerState> {
|
||||||
const general = context.general;
|
const general = context.general;
|
||||||
const currentNation = context.nation;
|
const currentNation = context.nation;
|
||||||
const destNation = context.destNation;
|
const destNation = context.destNation;
|
||||||
@@ -64,7 +66,8 @@ export class ActionResolver<
|
|||||||
const josaYi = JosaUtil.pick(generalName, '이');
|
const josaYi = JosaUtil.pick(generalName, '이');
|
||||||
|
|
||||||
// Self Log
|
// Self Log
|
||||||
context.addLog(`<D>${destNationName}</>${josaRo} 망명하여 수도로 이동합니다.`, { // Text says "Move to Capital", but logic might move to recruiter city.
|
context.addLog(`<D>${destNationName}</>${josaRo} 망명하여 수도로 이동합니다.`, {
|
||||||
|
// Text says "Move to Capital", but logic might move to recruiter city.
|
||||||
// Legacy log says "수도로 이동합니다", but implementation moves to destGeneral city if present!
|
// Legacy log says "수도로 이동합니다", but implementation moves to destGeneral city if present!
|
||||||
// We should match implementation or text? Text is just flavor.
|
// We should match implementation or text? Text is just flavor.
|
||||||
category: LogCategory.ACTION,
|
category: LogCategory.ACTION,
|
||||||
@@ -89,10 +92,15 @@ export class ActionResolver<
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 2. Recruiter Rewards
|
// 2. Recruiter Rewards
|
||||||
effects.push(createGeneralPatchEffect({
|
effects.push(
|
||||||
|
createGeneralPatchEffect(
|
||||||
|
{
|
||||||
experience: destGeneral.experience + 100,
|
experience: destGeneral.experience + 100,
|
||||||
dedication: destGeneral.dedication + 100,
|
dedication: destGeneral.dedication + 100,
|
||||||
}, destGeneral.id));
|
},
|
||||||
|
destGeneral.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// 3. Betrayal Logic
|
// 3. Betrayal Logic
|
||||||
// If currentNation exists (and > 0), handle betrayal return logic.
|
// If currentNation exists (and > 0), handle betrayal return logic.
|
||||||
@@ -107,7 +115,7 @@ export class ActionResolver<
|
|||||||
let newExp = general.experience;
|
let newExp = general.experience;
|
||||||
let newDed = general.dedication;
|
let newDed = general.dedication;
|
||||||
|
|
||||||
const betrayCount = (readMetaNumberFromUnknown(general.meta, 'betray') ?? 0);
|
const betrayCount = readMetaNumberFromUnknown(general.meta, 'betray') ?? 0;
|
||||||
let newBetray = betrayCount;
|
let newBetray = betrayCount;
|
||||||
|
|
||||||
if (currentNation && currentNation.id !== 0) {
|
if (currentNation && currentNation.id !== 0) {
|
||||||
@@ -125,16 +133,22 @@ export class ActionResolver<
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (returnGold > 0 || returnRice > 0) {
|
if (returnGold > 0 || returnRice > 0) {
|
||||||
effects.push(createNationPatchEffect({
|
effects.push(
|
||||||
|
createNationPatchEffect(
|
||||||
|
{
|
||||||
gold: currentNation.gold + returnGold,
|
gold: currentNation.gold + returnGold,
|
||||||
rice: currentNation.rice + returnRice
|
rice: currentNation.rice + returnRice,
|
||||||
}, currentNation.id));
|
},
|
||||||
|
currentNation.id
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Penalty
|
// Penalty
|
||||||
// 10% * betray count deduction
|
// 10% * betray count deduction
|
||||||
const penaltyFactor = 1 - (0.1 * betrayCount);
|
const penaltyFactor = 1 - 0.1 * betrayCount;
|
||||||
if (penaltyFactor < 0) { // Should not be less than 0? capped at ?
|
if (penaltyFactor < 0) {
|
||||||
|
// Should not be less than 0? capped at ?
|
||||||
// Legacy: (1 - 0.1 * betray).
|
// Legacy: (1 - 0.1 * betray).
|
||||||
}
|
}
|
||||||
// Apply penalty
|
// Apply penalty
|
||||||
@@ -152,7 +166,9 @@ export class ActionResolver<
|
|||||||
// If recruiter is not valid city?
|
// If recruiter is not valid city?
|
||||||
if (!targetCityId) targetCityId = destNation.capitalCityId!;
|
if (!targetCityId) targetCityId = destNation.capitalCityId!;
|
||||||
|
|
||||||
effects.push(createGeneralPatchEffect({
|
effects.push(
|
||||||
|
createGeneralPatchEffect(
|
||||||
|
{
|
||||||
nationId: destNation.id,
|
nationId: destNation.id,
|
||||||
cityId: targetCityId,
|
cityId: targetCityId,
|
||||||
experience: newExp,
|
experience: newExp,
|
||||||
@@ -170,8 +186,11 @@ export class ActionResolver<
|
|||||||
officer_city: 0,
|
officer_city: 0,
|
||||||
betray: newBetray,
|
betray: newBetray,
|
||||||
// killturn logic?
|
// killturn logic?
|
||||||
}
|
},
|
||||||
}, general.id));
|
},
|
||||||
|
general.id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// 5. Update Nations Gen Count (Visual only? or real count)
|
// 5. Update Nations Gen Count (Visual only? or real count)
|
||||||
// Legacy updates `gennum`.
|
// Legacy updates `gennum`.
|
||||||
@@ -214,7 +233,10 @@ export class ActionDefinition<
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(context: AcceptScoutResolveContext<TriggerState>, args: AcceptScoutArgs): GeneralActionOutcome<TriggerState> {
|
resolve(
|
||||||
|
context: AcceptScoutResolveContext<TriggerState>,
|
||||||
|
args: AcceptScoutArgs
|
||||||
|
): GeneralActionOutcome<TriggerState> {
|
||||||
return this.resolver.resolve(context, args);
|
return this.resolver.resolve(context, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ function createViewState(world: InMemoryWorld, year: number = 200, env: TurnComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('che_NPC능동', () => {
|
describe('che_NPC능동', () => {
|
||||||
|
|
||||||
it('should allow NPC to teleport with "순간이동"', async () => {
|
it('should allow NPC to teleport with "순간이동"', async () => {
|
||||||
const bootstrapResult = buildScenarioBootstrap({
|
const bootstrapResult = buildScenarioBootstrap({
|
||||||
scenario: MOCK_SCENARIO_BASE,
|
scenario: MOCK_SCENARIO_BASE,
|
||||||
@@ -125,7 +124,12 @@ describe('che_NPC능동', () => {
|
|||||||
experience: 0,
|
experience: 0,
|
||||||
dedication: 0,
|
dedication: 0,
|
||||||
officerLevel: 0,
|
officerLevel: 0,
|
||||||
role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
injury: 0,
|
injury: 0,
|
||||||
gold: 1000,
|
gold: 1000,
|
||||||
rice: 1000,
|
rice: 1000,
|
||||||
@@ -144,9 +148,11 @@ describe('che_NPC능동', () => {
|
|||||||
{
|
{
|
||||||
generalId: general.id,
|
generalId: general.id,
|
||||||
commandKey: 'che_NPC능동',
|
commandKey: 'che_NPC능동',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_NPC능동.js')).commandSpec.createDefinition({} as any),
|
resolver: (
|
||||||
|
await import('../../../src/actions/turn/general/che_NPC능동.js')
|
||||||
|
).commandSpec.createDefinition({} as any),
|
||||||
args: { optionText: '순간이동', destCityId },
|
args: { optionText: '순간이동', destCityId },
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updated = world.getGeneral(general.id);
|
const updated = world.getGeneral(general.id);
|
||||||
@@ -173,7 +179,12 @@ describe('che_NPC능동', () => {
|
|||||||
experience: 0,
|
experience: 0,
|
||||||
dedication: 0,
|
dedication: 0,
|
||||||
officerLevel: 0,
|
officerLevel: 0,
|
||||||
role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
injury: 0,
|
injury: 0,
|
||||||
gold: 1000,
|
gold: 1000,
|
||||||
rice: 1000,
|
rice: 1000,
|
||||||
@@ -188,7 +199,9 @@ describe('che_NPC능동', () => {
|
|||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
|
|
||||||
const def = (await import('../../../src/actions/turn/general/che_NPC능동.js')).commandSpec.createDefinition({} as any);
|
const def = (await import('../../../src/actions/turn/general/che_NPC능동.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
);
|
||||||
const args = { optionText: '순간이동', destCityId };
|
const args = { optionText: '순간이동', destCityId };
|
||||||
|
|
||||||
const ctx = createConstraintContext(general, 200, args);
|
const ctx = createConstraintContext(general, 200, args);
|
||||||
|
|||||||
@@ -35,11 +35,56 @@ const LINEAR_MAP: MapDefinition = {
|
|||||||
id: 'linear_map',
|
id: 'linear_map',
|
||||||
name: 'Linear Map',
|
name: 'Linear Map',
|
||||||
cities: [
|
cities: [
|
||||||
{ id: 101, name: 'City1', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [102], max: {} as any, initial: {} as any },
|
{
|
||||||
{ id: 102, name: 'City2', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [101, 103], max: {} as any, initial: {} as any },
|
id: 101,
|
||||||
{ id: 103, name: 'City3', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [102, 104], max: {} as any, initial: {} as any },
|
name: 'City1',
|
||||||
{ id: 104, name: 'City4', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [103, 105], max: {} as any, initial: {} as any },
|
level: 1,
|
||||||
{ id: 105, name: 'City5', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [104], max: {} as any, initial: {} as any },
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [102],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 102,
|
||||||
|
name: 'City2',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [101, 103],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 103,
|
||||||
|
name: 'City3',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [102, 104],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 104,
|
||||||
|
name: 'City4',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [103, 105],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 105,
|
||||||
|
name: 'City5',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [104],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
||||||
};
|
};
|
||||||
@@ -140,7 +185,12 @@ describe('che_강행', () => {
|
|||||||
experience: 1000,
|
experience: 1000,
|
||||||
dedication: 0,
|
dedication: 0,
|
||||||
officerLevel: 1,
|
officerLevel: 1,
|
||||||
role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
injury: 0,
|
injury: 0,
|
||||||
gold: 1000,
|
gold: 1000,
|
||||||
rice: 1000,
|
rice: 1000,
|
||||||
@@ -154,18 +204,29 @@ describe('che_강행', () => {
|
|||||||
meta: {},
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
|
|
||||||
// Move 101 -> 104 (dist 3) OK
|
// Move 101 -> 104 (dist 3) OK
|
||||||
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition({
|
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition(
|
||||||
|
{
|
||||||
scenarioConfig: { const: { develCost: 10 } } as any,
|
scenarioConfig: { const: { develCost: 10 } } as any,
|
||||||
worldRef: { listGenerals: () => world.getAllGenerals() } as any, // Mock world ref context
|
worldRef: { listGenerals: () => world.getAllGenerals() } as any, // Mock world ref context
|
||||||
map: LINEAR_MAP
|
map: LINEAR_MAP,
|
||||||
} as any);
|
} as any
|
||||||
|
);
|
||||||
|
|
||||||
await runner.runTurn([
|
await runner.runTurn([
|
||||||
{
|
{
|
||||||
@@ -175,9 +236,9 @@ describe('che_강행', () => {
|
|||||||
args: { destCityId: 104 },
|
args: { destCityId: 104 },
|
||||||
context: {
|
context: {
|
||||||
map: LINEAR_MAP,
|
map: LINEAR_MAP,
|
||||||
startDevelCost: 10
|
startDevelCost: 10,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updated = world.getGeneral(general.id);
|
const updated = world.getGeneral(general.id);
|
||||||
@@ -206,7 +267,12 @@ describe('che_강행', () => {
|
|||||||
experience: 1000,
|
experience: 1000,
|
||||||
dedication: 0,
|
dedication: 0,
|
||||||
officerLevel: 1,
|
officerLevel: 1,
|
||||||
role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
injury: 0,
|
injury: 0,
|
||||||
gold: 1000,
|
gold: 1000,
|
||||||
rice: 1000,
|
rice: 1000,
|
||||||
@@ -220,18 +286,29 @@ describe('che_강행', () => {
|
|||||||
meta: {},
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
|
|
||||||
// Move 101 -> 105 (dist 4) Fail
|
// Move 101 -> 105 (dist 4) Fail
|
||||||
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition({
|
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition(
|
||||||
|
{
|
||||||
scenarioConfig: { const: { develCost: 10 } } as any,
|
scenarioConfig: { const: { develCost: 10 } } as any,
|
||||||
worldRef: { listGenerals: () => world.getAllGenerals() } as any,
|
worldRef: { listGenerals: () => world.getAllGenerals() } as any,
|
||||||
map: LINEAR_MAP
|
map: LINEAR_MAP,
|
||||||
} as any);
|
} as any
|
||||||
|
);
|
||||||
|
|
||||||
// Manual constraint check
|
// Manual constraint check
|
||||||
const args = { destCityId: 105 };
|
const args = { destCityId: 105 };
|
||||||
@@ -258,35 +335,88 @@ describe('che_강행', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const leader: General = {
|
const leader: General = {
|
||||||
id: 1, name: 'Leader', nationId: 1, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Leader',
|
||||||
officerLevel: 12, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 50, atmos: 50, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 12,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 50,
|
||||||
|
atmos: 50,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const sub: General = {
|
const sub: General = {
|
||||||
id: 2, name: 'Sub', nationId: 1, cityId: 101, troopId: 0,
|
id: 2,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Sub',
|
||||||
officerLevel: 1, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 50, atmos: 50, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 50,
|
||||||
|
atmos: 50,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'RoamingNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0,
|
name: 'RoamingNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
level: 0, // Roaming
|
level: 0, // Roaming
|
||||||
typeCode: 'che_def', meta: {},
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.snapshot.generals.push(leader);
|
world.snapshot.generals.push(leader);
|
||||||
world.snapshot.generals.push(sub);
|
world.snapshot.generals.push(sub);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
|
|
||||||
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition({
|
const definition = (await import('../../../src/actions/turn/general/che_강행.js')).commandSpec.createDefinition(
|
||||||
|
{
|
||||||
scenarioConfig: { const: { develCost: 10 } } as any,
|
scenarioConfig: { const: { develCost: 10 } } as any,
|
||||||
worldRef: { listGenerals: () => world.getAllGenerals() } as any, // Must return valid list
|
worldRef: { listGenerals: () => world.getAllGenerals() } as any, // Must return valid list
|
||||||
map: LINEAR_MAP
|
map: LINEAR_MAP,
|
||||||
} as any);
|
} as any
|
||||||
|
);
|
||||||
|
|
||||||
await runner.runTurn([
|
await runner.runTurn([
|
||||||
{
|
{
|
||||||
@@ -297,9 +427,9 @@ describe('che_강행', () => {
|
|||||||
context: {
|
context: {
|
||||||
map: LINEAR_MAP,
|
map: LINEAR_MAP,
|
||||||
startDevelCost: 10,
|
startDevelCost: 10,
|
||||||
moveGenerals: world.getAllGenerals()
|
moveGenerals: world.getAllGenerals(),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updatedLeader = world.getGeneral(leader.id);
|
const updatedLeader = world.getGeneral(leader.id);
|
||||||
|
|||||||
@@ -35,9 +35,36 @@ const LINEAR_MAP: MapDefinition = {
|
|||||||
id: 'linear_map',
|
id: 'linear_map',
|
||||||
name: 'Linear Map',
|
name: 'Linear Map',
|
||||||
cities: [
|
cities: [
|
||||||
{ id: 101, name: 'CapitalCity', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [102], max: {} as any, initial: {} as any },
|
{
|
||||||
{ id: 102, name: 'OtherCity', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [101, 103], max: {} as any, initial: {} as any },
|
id: 101,
|
||||||
{ id: 103, name: 'OfficerCity', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [102], max: {} as any, initial: {} as any },
|
name: 'CapitalCity',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [102],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 102,
|
||||||
|
name: 'OtherCity',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [101, 103],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 103,
|
||||||
|
name: 'OfficerCity',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [102],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
||||||
};
|
};
|
||||||
@@ -78,7 +105,7 @@ function createConstraintContext(actor: General, year: number = 200, args: any =
|
|||||||
world: { currentYear: year },
|
world: { currentYear: year },
|
||||||
openingPartYear: systemEnv.openingPartYear,
|
openingPartYear: systemEnv.openingPartYear,
|
||||||
map: LINEAR_MAP,
|
map: LINEAR_MAP,
|
||||||
cities: LINEAR_MAP.cities
|
cities: LINEAR_MAP.cities,
|
||||||
},
|
},
|
||||||
mode: 'full',
|
mode: 'full',
|
||||||
};
|
};
|
||||||
@@ -119,7 +146,6 @@ function createViewState(world: InMemoryWorld, year: number = 200, env: TurnComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('che_귀환', () => {
|
describe('che_귀환', () => {
|
||||||
|
|
||||||
it('should return to capital if normal officer', async () => {
|
it('should return to capital if normal officer', async () => {
|
||||||
const bootstrapResult = buildScenarioBootstrap({
|
const bootstrapResult = buildScenarioBootstrap({
|
||||||
scenario: MOCK_SCENARIO_BASE,
|
scenario: MOCK_SCENARIO_BASE,
|
||||||
@@ -129,14 +155,45 @@ describe('che_귀환', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const general: General = {
|
const general: General = {
|
||||||
id: 1, name: 'NormalOfficer', nationId: 1, cityId: 102, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'NormalOfficer',
|
||||||
officerLevel: 1, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 102,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
@@ -145,9 +202,11 @@ describe('che_귀환', () => {
|
|||||||
{
|
{
|
||||||
generalId: general.id,
|
generalId: general.id,
|
||||||
commandKey: 'che_귀환',
|
commandKey: 'che_귀환',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition({} as any),
|
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
),
|
||||||
args: {},
|
args: {},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updated = world.getGeneral(general.id);
|
const updated = world.getGeneral(general.id);
|
||||||
@@ -168,15 +227,45 @@ describe('che_귀환', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const general: General = {
|
const general: General = {
|
||||||
id: 1, name: 'Governor', nationId: 1, cityId: 102, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Governor',
|
||||||
officerLevel: 4, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
cityId: 102,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 4,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { officer_city: 103 },
|
meta: { officer_city: 103 },
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
@@ -185,9 +274,11 @@ describe('che_귀환', () => {
|
|||||||
{
|
{
|
||||||
generalId: general.id,
|
generalId: general.id,
|
||||||
commandKey: 'che_귀환',
|
commandKey: 'che_귀환',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition({} as any),
|
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
),
|
||||||
args: {},
|
args: {},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updated = world.getGeneral(general.id);
|
const updated = world.getGeneral(general.id);
|
||||||
@@ -202,19 +293,52 @@ describe('che_귀환', () => {
|
|||||||
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
||||||
|
|
||||||
const general: General = {
|
const general: General = {
|
||||||
id: 1, name: 'AlreadyHome', nationId: 1, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'AlreadyHome',
|
||||||
officerLevel: 1, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
|
|
||||||
const def = (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition({} as any);
|
const def = (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
);
|
||||||
const args = {};
|
const args = {};
|
||||||
|
|
||||||
const ctx = createConstraintContext(general, 200, args);
|
const ctx = createConstraintContext(general, 200, args);
|
||||||
@@ -251,15 +375,45 @@ describe('che_귀환', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const general: General = {
|
const general: General = {
|
||||||
id: 1, name: 'GovernorAtHome', nationId: 1, cityId: 103, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'GovernorAtHome',
|
||||||
officerLevel: 4, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
cityId: 103,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 4,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { officer_city: 103 },
|
meta: { officer_city: 103 },
|
||||||
};
|
};
|
||||||
const nation: Nation = {
|
const nation: Nation = {
|
||||||
id: 1, name: 'MyNation', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'MyNation',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.nations.push(nation);
|
world.snapshot.nations.push(nation);
|
||||||
@@ -271,9 +425,11 @@ describe('che_귀환', () => {
|
|||||||
{
|
{
|
||||||
generalId: general.id,
|
generalId: general.id,
|
||||||
commandKey: 'che_귀환',
|
commandKey: 'che_귀환',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition({} as any),
|
resolver: (await import('../../../src/actions/turn/general/che_귀환.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
),
|
||||||
args: {},
|
args: {},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updated = world.getGeneral(general.id);
|
const updated = world.getGeneral(general.id);
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import type { General, Nation } from '../../../src/domain/entities.js';
|
import type { General, Nation } from '../../../src/domain/entities.js';
|
||||||
import { buildScenarioBootstrap } from '../../../src/world/bootstrap.js';
|
import { buildScenarioBootstrap } from '../../../src/world/bootstrap.js';
|
||||||
@@ -36,8 +35,26 @@ const MINIMAL_MAP = {
|
|||||||
id: 'minimal_map',
|
id: 'minimal_map',
|
||||||
name: 'Minimal Map',
|
name: 'Minimal Map',
|
||||||
cities: [
|
cities: [
|
||||||
{ id: 101, name: 'Capital1', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [], max: {} as any, initial: {} as any },
|
{
|
||||||
{ id: 102, name: 'Capital2', level: 1, region: 1, position: { x: 0, y: 0 }, connections: [], max: {} as any, initial: {} as any },
|
id: 101,
|
||||||
|
name: 'Capital1',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 102,
|
||||||
|
name: 'Capital2',
|
||||||
|
level: 1,
|
||||||
|
region: 1,
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
connections: [],
|
||||||
|
max: {} as any,
|
||||||
|
initial: {} as any,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
defaults: { trust: 50, trade: 100, supplyState: 1, frontState: 0 },
|
||||||
};
|
};
|
||||||
@@ -78,7 +95,7 @@ function createConstraintContext(actor: General, year: number = 200, args: any =
|
|||||||
world: { currentYear: year },
|
world: { currentYear: year },
|
||||||
openingPartYear: systemEnv.openingPartYear,
|
openingPartYear: systemEnv.openingPartYear,
|
||||||
map: MINIMAL_MAP,
|
map: MINIMAL_MAP,
|
||||||
cities: MINIMAL_MAP.cities
|
cities: MINIMAL_MAP.cities,
|
||||||
},
|
},
|
||||||
mode: 'full',
|
mode: 'full',
|
||||||
};
|
};
|
||||||
@@ -131,21 +148,70 @@ describe('che_등용수락', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const neutralGen: General = {
|
const neutralGen: General = {
|
||||||
id: 1, name: 'Neutral', nationId: 0, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Neutral',
|
||||||
officerLevel: 0, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 0,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 0,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const recruiterGen: General = {
|
const recruiterGen: General = {
|
||||||
id: 2, name: 'Recruiter', nationId: 2, cityId: 102, troopId: 0,
|
id: 2,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Recruiter',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
nationId: 2,
|
||||||
|
cityId: 102,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const nation2: Nation = {
|
const nation2: Nation = {
|
||||||
id: 2, name: 'Nation2', color: '#000', capitalCityId: 102, chiefGeneralId: 2,
|
id: 2,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation2',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 102,
|
||||||
|
chiefGeneralId: 2,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.snapshot.generals.push(neutralGen);
|
world.snapshot.generals.push(neutralGen);
|
||||||
@@ -156,14 +222,16 @@ describe('che_등용수락', () => {
|
|||||||
{
|
{
|
||||||
generalId: neutralGen.id,
|
generalId: neutralGen.id,
|
||||||
commandKey: 'che_등용수락',
|
commandKey: 'che_등용수락',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition({} as any),
|
resolver: (
|
||||||
|
await import('../../../src/actions/turn/general/che_등용수락.js')
|
||||||
|
).commandSpec.createDefinition({} as any),
|
||||||
args: { destNationId: 2, destGeneralId: 2 },
|
args: { destNationId: 2, destGeneralId: 2 },
|
||||||
context: {
|
context: {
|
||||||
destNation: nation2,
|
destNation: nation2,
|
||||||
destGeneral: recruiterGen,
|
destGeneral: recruiterGen,
|
||||||
env: systemEnv
|
env: systemEnv,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updatedSelf = world.getGeneral(neutralGen.id);
|
const updatedSelf = world.getGeneral(neutralGen.id);
|
||||||
@@ -188,24 +256,77 @@ describe('che_등용수락', () => {
|
|||||||
const runner = new TestGameRunner(world, 200, 1);
|
const runner = new TestGameRunner(world, 200, 1);
|
||||||
|
|
||||||
const betrayer: General = {
|
const betrayer: General = {
|
||||||
id: 1, name: 'Betrayer', nationId: 1, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 1000, dedication: 1000,
|
name: 'Betrayer',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 2000, rice: 2000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
nationId: 1,
|
||||||
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 1000,
|
||||||
|
dedication: 1000,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 2000,
|
||||||
|
rice: 2000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
meta: { betray: 1 },
|
meta: { betray: 1 },
|
||||||
};
|
};
|
||||||
const nation1: Nation = {
|
const nation1: Nation = {
|
||||||
id: 1, name: 'Nation1', color: '#000', capitalCityId: 101, chiefGeneralId: 0,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation1',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 0,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const recruiterGen: General = {
|
const recruiterGen: General = {
|
||||||
id: 2, name: 'Recruiter', nationId: 2, cityId: 102, troopId: 0,
|
id: 2,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Recruiter',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
nationId: 2,
|
||||||
|
cityId: 102,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation2: Nation = {
|
const nation2: Nation = {
|
||||||
id: 2, name: 'Nation2', color: '#000', capitalCityId: 102, chiefGeneralId: 2,
|
id: 2,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation2',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 102,
|
||||||
|
chiefGeneralId: 2,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.snapshot.generals.push(betrayer);
|
world.snapshot.generals.push(betrayer);
|
||||||
@@ -217,14 +338,16 @@ describe('che_등용수락', () => {
|
|||||||
{
|
{
|
||||||
generalId: betrayer.id,
|
generalId: betrayer.id,
|
||||||
commandKey: 'che_등용수락',
|
commandKey: 'che_등용수락',
|
||||||
resolver: (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition({} as any),
|
resolver: (
|
||||||
|
await import('../../../src/actions/turn/general/che_등용수락.js')
|
||||||
|
).commandSpec.createDefinition({} as any),
|
||||||
args: { destNationId: 2, destGeneralId: 2 },
|
args: { destNationId: 2, destGeneralId: 2 },
|
||||||
context: {
|
context: {
|
||||||
destNation: nation2,
|
destNation: nation2,
|
||||||
destGeneral: recruiterGen,
|
destGeneral: recruiterGen,
|
||||||
env: systemEnv
|
env: systemEnv,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const updatedSelf = world.getGeneral(betrayer.id);
|
const updatedSelf = world.getGeneral(betrayer.id);
|
||||||
@@ -248,23 +371,81 @@ describe('che_등용수락', () => {
|
|||||||
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
||||||
|
|
||||||
const monarch: General = {
|
const monarch: General = {
|
||||||
id: 1, name: 'Monarch', nationId: 1, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Monarch',
|
||||||
officerLevel: 12, role: { personality: null, specialDomestic: null, specialWar: null, items: { horse: null, weapon: null, book: null, item: null } },
|
nationId: 1,
|
||||||
injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 12,
|
||||||
|
role: {
|
||||||
|
personality: null,
|
||||||
|
specialDomestic: null,
|
||||||
|
specialWar: null,
|
||||||
|
items: { horse: null, weapon: null, book: null, item: null },
|
||||||
|
},
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation1: Nation = {
|
const nation1: Nation = {
|
||||||
id: 1, name: 'Nation1', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation1',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const recruiterGen: General = {
|
const recruiterGen: General = {
|
||||||
id: 2, name: 'Recruiter', nationId: 2, cityId: 102, troopId: 0,
|
id: 2,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Recruiter',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
nationId: 2,
|
||||||
|
cityId: 102,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation2: Nation = {
|
const nation2: Nation = {
|
||||||
id: 2, name: 'Nation2', color: '#000', capitalCityId: 102, chiefGeneralId: 2,
|
id: 2,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation2',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 102,
|
||||||
|
chiefGeneralId: 2,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.snapshot.generals.push(monarch);
|
world.snapshot.generals.push(monarch);
|
||||||
@@ -273,7 +454,9 @@ describe('che_등용수락', () => {
|
|||||||
world.snapshot.nations.push(nation2);
|
world.snapshot.nations.push(nation2);
|
||||||
|
|
||||||
// Manually check constraints for denial
|
// Manually check constraints for denial
|
||||||
const def = (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition({} as any);
|
const def = (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
);
|
||||||
const args = { destNationId: 2, destGeneralId: 2 };
|
const args = { destNationId: 2, destGeneralId: 2 };
|
||||||
|
|
||||||
const ctx = createConstraintContext(monarch, 200, args);
|
const ctx = createConstraintContext(monarch, 200, args);
|
||||||
@@ -298,27 +481,74 @@ describe('che_등용수락', () => {
|
|||||||
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
const world = new InMemoryWorld(bootstrapResult.snapshot);
|
||||||
|
|
||||||
const general: General = {
|
const general: General = {
|
||||||
id: 1, name: 'Gen1', nationId: 1, cityId: 101, troopId: 0,
|
id: 1,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Gen1',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
nationId: 1,
|
||||||
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
const nation1: Nation = {
|
const nation1: Nation = {
|
||||||
id: 1, name: 'Nation1', color: '#000', capitalCityId: 101, chiefGeneralId: 1,
|
id: 1,
|
||||||
gold: 0, rice: 0, power: 0, level: 1, typeCode: 'che_def', meta: {},
|
name: 'Nation1',
|
||||||
|
color: '#000',
|
||||||
|
capitalCityId: 101,
|
||||||
|
chiefGeneralId: 1,
|
||||||
|
gold: 0,
|
||||||
|
rice: 0,
|
||||||
|
power: 0,
|
||||||
|
level: 1,
|
||||||
|
typeCode: 'che_def',
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
// Recruiter also in same nation? Or different?
|
// Recruiter also in same nation? Or different?
|
||||||
// Arg destNationId is key.
|
// Arg destNationId is key.
|
||||||
const recruiterGen: General = {
|
const recruiterGen: General = {
|
||||||
id: 2, name: 'Recruiter', nationId: 1, cityId: 101, troopId: 0,
|
id: 2,
|
||||||
stats: { leadership: 50, strength: 50, intelligence: 50 }, experience: 0, dedication: 0,
|
name: 'Recruiter',
|
||||||
officerLevel: 1, role: null as any, injury: 0, gold: 1000, rice: 1000, crew: 0, crewTypeId: 0, train: 0, atmos: 0, age: 20, npcState: 0, triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} }, meta: {},
|
nationId: 1,
|
||||||
|
cityId: 101,
|
||||||
|
troopId: 0,
|
||||||
|
stats: { leadership: 50, strength: 50, intelligence: 50 },
|
||||||
|
experience: 0,
|
||||||
|
dedication: 0,
|
||||||
|
officerLevel: 1,
|
||||||
|
role: null as any,
|
||||||
|
injury: 0,
|
||||||
|
gold: 1000,
|
||||||
|
rice: 1000,
|
||||||
|
crew: 0,
|
||||||
|
crewTypeId: 0,
|
||||||
|
train: 0,
|
||||||
|
atmos: 0,
|
||||||
|
age: 20,
|
||||||
|
npcState: 0,
|
||||||
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
||||||
|
meta: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.snapshot.generals.push(general);
|
world.snapshot.generals.push(general);
|
||||||
world.snapshot.generals.push(recruiterGen);
|
world.snapshot.generals.push(recruiterGen);
|
||||||
world.snapshot.nations.push(nation1);
|
world.snapshot.nations.push(nation1);
|
||||||
|
|
||||||
const def = (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition({} as any);
|
const def = (await import('../../../src/actions/turn/general/che_등용수락.js')).commandSpec.createDefinition(
|
||||||
|
{} as any
|
||||||
|
);
|
||||||
const args = { destNationId: 1, destGeneralId: 2 }; // Target same nation 1
|
const args = { destNationId: 1, destGeneralId: 2 }; // Target same nation 1
|
||||||
|
|
||||||
const ctx = createConstraintContext(general, 200, args);
|
const ctx = createConstraintContext(general, 200, args);
|
||||||
|
|||||||
Reference in New Issue
Block a user