feat: add non-aggression proposal and acceptance actions with constraints

This commit is contained in:
2026-01-02 18:33:24 +00:00
parent cb86a47f94
commit 10ff64946e
8 changed files with 524 additions and 5 deletions
+48 -1
View File
@@ -1,5 +1,11 @@
import type { General } from '../domain/entities.js';
import { allow, readDestGeneral, resolveDestGeneralId, unknownOrDeny } from './helpers.js';
import {
allow,
readDestGeneral,
resolveDestGeneralId,
resolveDestNationId,
unknownOrDeny,
} from './helpers.js';
import type { Constraint, ConstraintContext, RequirementKey, StateView } from './types.js';
export const notBeNeutral = (): Constraint => ({
@@ -172,6 +178,47 @@ export const existsDestGeneral = (): Constraint => ({
},
});
export const destGeneralInDestNation = (): Constraint => ({
name: 'DestGeneralInDestNation',
requires: (ctx) => {
const reqs: RequirementKey[] = [];
const destGeneralId = resolveDestGeneralId(ctx);
if (destGeneralId !== undefined) {
reqs.push({ kind: 'destGeneral', id: destGeneralId });
}
const destNationId = resolveDestNationId(ctx);
if (destNationId !== undefined) {
reqs.push({ kind: 'destNation', id: destNationId });
}
return reqs;
},
test: (ctx, view) => {
const destGeneral = readDestGeneral(ctx, view);
if (!destGeneral) {
const destGeneralId = resolveDestGeneralId(ctx);
if (destGeneralId === undefined) {
return unknownOrDeny(ctx, [], '장수 정보가 없습니다.');
}
const req: RequirementKey = {
kind: 'destGeneral',
id: destGeneralId,
};
return unknownOrDeny(ctx, [req], '장수 정보가 없습니다.');
}
const destNationId = resolveDestNationId(ctx);
if (destNationId === undefined) {
return unknownOrDeny(ctx, [], '국가 정보가 없습니다.');
}
if (destGeneral.nationId !== destNationId) {
return {
kind: 'deny',
reason: '제의 장수가 국가 소속이 아닙니다.',
};
}
return allow();
},
});
export const friendlyDestGeneral = (): Constraint => ({
name: 'FriendlyDestGeneral',
requires: (ctx) => {
+47 -1
View File
@@ -1,5 +1,12 @@
import type { General, Nation } from '../domain/entities.js';
import { allow, readMetaNumber, readNation, resolveDestNationId, unknownOrDeny } from './helpers.js';
import {
allow,
readGeneral,
readMetaNumber,
readNation,
resolveDestNationId,
unknownOrDeny,
} from './helpers.js';
import type { Constraint, ConstraintContext, RequirementKey, StateView } from './types.js';
export const notWanderingNation = (): Constraint => ({
@@ -166,3 +173,42 @@ export const existsDestNation = (): Constraint => ({
return allow();
},
});
export const differentDestNation = (): Constraint => ({
name: 'DifferentDestNation',
requires: (ctx) => {
const reqs: RequirementKey[] = [];
if (ctx.nationId !== undefined) {
reqs.push({ kind: 'nation', id: ctx.nationId });
} else {
reqs.push({ kind: 'general', id: ctx.actorId });
}
const destNationId = resolveDestNationId(ctx);
if (destNationId !== undefined) {
reqs.push({ kind: 'destNation', id: destNationId });
}
return reqs;
},
test: (ctx, view) => {
const destNationId = resolveDestNationId(ctx);
if (destNationId === undefined) {
return unknownOrDeny(ctx, [], '국가 정보가 없습니다.');
}
let baseNationId = ctx.nationId;
if (baseNationId === undefined) {
const general = readGeneral(ctx, view);
if (!general) {
const req: RequirementKey = {
kind: 'general',
id: ctx.actorId,
};
return unknownOrDeny(ctx, [req], '국가 정보가 없습니다.');
}
baseNationId = general.nationId;
}
if (baseNationId === destNationId) {
return { kind: 'deny', reason: '같은 국가입니다.' };
}
return allow();
},
});