merge: add sabotage constraint parity

This commit is contained in:
2026-07-26 04:13:13 +00:00
3 changed files with 46 additions and 8 deletions
@@ -8,14 +8,16 @@
- 범위: 명령 결과, RNG 소비, 로그, 예약 턴 lifecycle, DB 영속화
현재 ref MariaDB와 core memory를 잇는 공통 runner, 성공 경로 55개,
실행 중 확률 실패 9개, full constraint fallback 7개와 모략 확률 clamp
실행 중 확률 실패 9개, full constraint fallback 12개와 모략 확률 clamp
8개, 모략 결과값 경계 5개, 부상 경계 3개가 구현됐다.
실패 9개는 내정 critical
`주민선정/정착장려/상업투자/기술연구/물자조달`과 모략
`화계/선동/파괴/탈취`이며 RNG 전체 trace, semantic state delta와 실패
로그 본문을 비교한다. 제약 7개는 무소속, 방랑국, 타국 도시, 보급 단절,
금·쌀 부족과 민심 상한을 대표하며 휴식 fallback과 RNG/state delta를
비교한다. clamp 8개는 `화계/선동/파괴/탈취` 각각의 계산 확률 0과
로그 본문을 비교한다. 공통 제약 7개는 무소속, 방랑국, 타국 도시, 보급
단절, 금·쌀 부족과 민심 상한을 대표한다. 모략 제약 5개는 동일 도시,
중립 도시, 불가침국, 계략 비용 금·쌀 부족을 고정한다. 모두 휴식
fallback과 RNG/state delta를 비교한다. clamp 8개는
`화계/선동/파괴/탈취` 각각의 계산 확률 0과
0.5 경계에서 성공 판정 RNG의 무소비 또는 `nextBits(1)` 소비와 전체
state delta를 비교한다. 결과값 5개는 화계 농업·상업, 선동 치안·민심,
파괴 수비·성벽의 0 바닥과 탈취의 대상 국가 자원 상한·미보급 도시 최종
@@ -179,10 +179,12 @@ responses pass a separate reference trace and core resolver/API boundary.
Nine general in-action failure cases now also pass the common differential:
five domestic critical failures and four sabotage failures. They compare the
full command RNG trace, semantic state delta and the exact action-log body.
Seven full-constraint cases cover neutral status, wandering nation, city
ownership, supply, gold, rice and trust-cap rejection. Both engines replace
the denied command with rest, consume the same RNG and produce the same
semantic delta. Eight sabotage clamp cases cover probability zero and 0.5 for
Seven common full-constraint cases cover neutral status, wandering nation,
city ownership, supply, gold, rice and trust-cap rejection. Five sabotage
constraint cases add the occupied-city target, neutral target, non-aggression
status and insufficient sabotage gold or rice. Both engines replace the denied
command with rest, consume the same RNG and produce the same semantic delta.
Eight sabotage clamp cases cover probability zero and 0.5 for
fire attack, agitation, destruction and seizure. The zero boundary skips the
success RNG primitive, while exactly 0.5 consumes `nextBits(1)`; the complete
RNG trace and semantic delta match. These cases also fixed fire-attack city
@@ -763,6 +763,40 @@ const constraintCases: GeneralConstraintCase[] = [
action: 'che_주민선정',
fixturePatches: { cities: { 3: { trust: 100 } } },
},
{
name: 'sabotage targets the occupied city',
action: 'che_화계',
args: { destCityID: 3 },
},
{
name: 'sabotage targets a neutral city',
action: 'che_화계',
args: { destCityID: 70 },
fixturePatches: { cities: { 70: { nationId: 0 } } },
},
{
name: 'sabotage targets a non-aggression nation',
action: 'che_화계',
args: { destCityID: 70 },
fixturePatches: {
diplomacy: {
'1:2': { state: 7 },
'2:1': { state: 7 },
},
},
},
{
name: 'insufficient sabotage gold',
action: 'che_화계',
args: { destCityID: 70 },
actorPatch: { gold: 0 },
},
{
name: 'insufficient sabotage rice',
action: 'che_화계',
args: { destCityID: 70 },
actorPatch: { rice: 0 },
},
];
integration('general command full-constraint fallback matrix', () => {