diff --git a/docs/architecture/legacy-commands.md b/docs/architecture/legacy-commands.md new file mode 100644 index 0000000..7ce552b --- /dev/null +++ b/docs/architecture/legacy-commands.md @@ -0,0 +1,136 @@ +# Legacy Command Catalog + +This file lists the command keys available under `legacy/hwe/sammo/Command/`. +Command keys match class names and file names; they are the values stored in +`general_turn.action` and `nation_turn.action`. + +## Command Resolution + +- General: `buildGeneralCommandClass($type)` in `legacy/hwe/func_converter.php` +- Nation: `buildNationCommandClass($type)` in `legacy/hwe/func_converter.php` +- `null` or empty `type` defaults to `휴식` +- Post-req turn cooldowns are stored in: + - `next_execute` KV (per general) + - `nation_env` KV (per nation) + +## Execution Semantics (BaseCommand) + +- Conditions are checked via constraint sets (permission/min/full). +- `getPreReqTurn()` is enforced by `LastTurn` term stacking. +- `getPostReqTurn()` is enforced by `next_execute` (cooldown). +- If `run()` returns `false`, `getAlternativeCommand()` may be used. + +## Command Prefixes and Scenarios + +Command keys are scenario-driven. The prefixes (e.g. `che_`, `cr_`, `event_`) +identify the rule set or scenario extension, and the active scenario chooses +which commands are available via `GameConst` overrides. See +`docs/architecture/legacy-scenarios.md` for details. + +## General Commands (`legacy/hwe/sammo/Command/General/`) + +| Key | Display name (actionName) | +| --- | --- | +| `che_NPC능동` | `NPC능동` | +| `che_강행` | `강행` | +| `che_거병` | `거병` | +| `che_건국` | `건국` | +| `che_견문` | `견문` | +| `che_군량매매` | `군량매매` | +| `che_귀환` | `귀환` | +| `che_기술연구` | `기술 연구` | +| `che_내정특기초기화` | `내정 특기 초기화` | +| `che_농지개간` | `농지 개간` | +| `che_단련` | `단련` | +| `che_등용` | `등용` | +| `che_등용수락` | `등용 수락` | +| `che_랜덤임관` | `무작위 국가로 임관` | +| `che_모반시도` | `모반시도` | +| `che_모병` | `모병` | +| `che_무작위건국` | `무작위 도시 건국` | +| `che_물자조달` | `물자조달` | +| `che_방랑` | `방랑` | +| `che_사기진작` | `사기진작` | +| `che_상업투자` | `상업 투자` | +| `che_선동` | `선동` | +| `che_선양` | `선양` | +| `che_성벽보수` | `성벽 보수` | +| `che_소집해제` | `소집해제` | +| `che_수비강화` | `수비 강화` | +| `che_숙련전환` | `숙련전환` | +| `che_요양` | `요양` | +| `che_은퇴` | `은퇴` | +| `che_이동` | `이동` | +| `che_인재탐색` | `인재탐색` | +| `che_임관` | `임관` | +| `che_장비매매` | `장비매매` | +| `che_장수대상임관` | `장수를 따라 임관` | +| `che_전투태세` | `전투태세` | +| `che_전투특기초기화` | `전투 특기 초기화` | +| `che_접경귀환` | `접경귀환` | +| `che_정착장려` | `정착 장려` | +| `che_주민선정` | `주민 선정` | +| `che_증여` | `증여` | +| `che_집합` | `집합` | +| `che_징병` | `징병` | +| `che_첩보` | `첩보` | +| `che_출병` | `출병` | +| `che_치안강화` | `치안 강화` | +| `che_탈취` | `탈취` | +| `che_파괴` | `파괴` | +| `che_하야` | `하야` | +| `che_해산` | `해산` | +| `che_헌납` | `헌납` | +| `che_화계` | `화계` | +| `che_훈련` | `훈련` | +| `cr_건국` | `건국` | +| `cr_맹훈련` | `맹훈련` | +| `휴식` | `휴식` | + +## Nation Commands (`legacy/hwe/sammo/Command/Nation/`) + +| Key | Display name (actionName) | +| --- | --- | +| `che_감축` | `감축` | +| `che_국기변경` | `국기변경` | +| `che_국호변경` | `국호변경` | +| `che_급습` | `급습` | +| `che_몰수` | `몰수` | +| `che_무작위수도이전` | `무작위 수도 이전` | +| `che_물자원조` | `원조` | +| `che_발령` | `발령` | +| `che_백성동원` | `백성동원` | +| `che_부대탈퇴지시` | `부대 탈퇴 지시` | +| `che_불가침수락` | `불가침 수락` | +| `che_불가침제의` | `불가침 제의` | +| `che_불가침파기수락` | `불가침 파기 수락` | +| `che_불가침파기제의` | `불가침 파기 제의` | +| `che_선전포고` | `선전포고` | +| `che_수몰` | `수몰` | +| `che_의병모집` | `의병모집` | +| `che_이호경식` | `이호경식` | +| `che_종전수락` | `종전 수락` | +| `che_종전제의` | `종전 제의` | +| `che_증축` | `증축` | +| `che_천도` | `천도` | +| `che_초토화` | `초토화` | +| `che_포상` | `포상` | +| `che_피장파장` | `피장파장` | +| `che_필사즉생` | `필사즉생` | +| `che_허보` | `허보` | +| `cr_인구이동` | `인구이동` | +| `event_극병연구` | `극병 연구` | +| `event_대검병연구` | `대검병 연구` | +| `event_무희연구` | `무희 연구` | +| `event_산저병연구` | `산저병 연구` | +| `event_상병연구` | `상병 연구` | +| `event_원융노병연구` | `원융노병 연구` | +| `event_음귀병연구` | `음귀병 연구` | +| `event_화륜차연구` | `화륜차 연구` | +| `event_화시병연구` | `화시병 연구` | +| `휴식` | `휴식` | + +## Open Questions / Follow-ups + +- Prefix semantics (`che_`, `cr_`, `event_`) are not documented here and may be + scenario- or mode-specific. diff --git a/docs/architecture/legacy-engine-execution.md b/docs/architecture/legacy-engine-execution.md new file mode 100644 index 0000000..4102323 --- /dev/null +++ b/docs/architecture/legacy-engine-execution.md @@ -0,0 +1,121 @@ +# Legacy Engine Execution Flow + +This document summarizes how the legacy engine advances turns and executes +commands. It focuses on the execution pipeline, RNG seeding, and state writes +based on `legacy/hwe/sammo/API/Global/ExecuteEngine.php`, +`legacy/hwe/sammo/TurnExecutionHelper.php`, and `legacy/hwe/sammo/Command/BaseCommand.php`. + +## Entry Point: ExecuteEngine API + +- Endpoint: `legacy/hwe/sammo/API/Global/ExecuteEngine.php` +- Session: no session required (`NO_SESSION`) +- Optional `serverID` guard via `UniqueConst::$serverID` +- Calls `TurnExecutionHelper::executeAllCommand($updated, $locked)` +- Returns `{ updated, locked, lastExecuted }` + +## Global Turn Loop (`TurnExecutionHelper::executeAllCommand`) + +1. **Time gate** + - If `now < game_env.turntime`, return without executing. +2. **Locking** + - `tryLock()` on `plock` row (`type='GAME'`). + - If locked or `isunited` in `2|3`, return (frozen state). +3. **Pre-turn maintenance** + - Cache game env, `checkDelay()`, `updateOnline()`, `CheckOverhead()`. +4. **Catch-up monthly loop** + - Compute `prevTurn = cutTurn(turntime, turnterm)` and `nextTurn = addTurn(prevTurn)`. + - While `nextTurn <= now`: + - `executeGeneralCommandUntil(nextTurn, limitActionTime, year, month)` + - `updateTraffic()` + - Monthly pipeline: + - `runEventHandler(PreMonth)` + - `preUpdateMonthly()` + - `turnDate(nextTurn)` + - `checkStatistic()` (only if `month == 1`) + - `runEventHandler(Month)` + - `postUpdateMonthly($monthlyRng)` + - Advance `prevTurn`, `nextTurn`, update `game_env.turntime`. +5. **Current partial month** + - `turnDate(prevTurn)` + - `executeGeneralCommandUntil(now, limitActionTime, year, month)` +6. **Post-turn maintenance** + - `processTournament()` + - `processAuction()` + - Reset cache, `unlock()`. + +`limitActionTime` is derived from `max_execution_time` (roughly 2/3 of the +configured limit). If time runs out mid-loop, it returns early and keeps +`game_env.turntime` at the most recent executed value. + +## Per-General Execution (`executeGeneralCommandUntil`) + +For each general with `turntime < targetDate` (ordered by `turntime, no`): + +1. **Load state** + - `General::createObjFromDB()` and `KVStorage` for `game_env`. +2. **Nation command (if officer_level >= 5)** + - Pull `nation_turn` row for `turn_idx = 0`. + - Build `NationCommand` with `LastTurn` stored in `nation_env`. +3. **AI/autorun** + - NPCs (`npc >= 2`) or players past `autorun_limit` use `GeneralAI`. + - AI can replace both nation and general commands. +4. **Preprocess triggers** + - RNG seed: `hiddenSeed + 'preprocess' + year + month + generalID`. + - `preprocessCommand()` merges action triggers + `che_부상경감`, `che_병력군량소모`. +5. **Blocked users** + - `processBlocked()` consumes `killturn` and logs if `block >= 2`. +6. **Execute nation command** + - RNG seed: `hiddenSeed + 'nationCommand' + year + month + generalID + commandKey`. + - `processNationCommand()` checks conditions, term stack, `run()`. + - If `run()` fails and `getAlternativeCommand()` exists, it retries. + - Updates `nation_env` with `LastTurn` result. +7. **Execute general command** + - Load from `general_turn` (`turn_idx = 0`), default to `휴식`. + - RNG seed: `hiddenSeed + 'generalCommand' + year + month + generalID + commandKey`. + - `processCommand()` checks conditions, term stack, `run()`. + - Updates `killturn` based on NPC status, autorun, or `휴식`. +8. **Queue maintenance & turntime** + - `pullNationCommand()` / `pullGeneralCommand()` advance queues. + - `updateTurnTime()` handles deletion/retirement and sets next `turntime`. + - Persist via `General::applyDB()`. + +## Command Semantics (BaseCommand) + +- **Constraints**: permission/min/full conditions are evaluated via + `Constraint::testAll()` with `general/city/nation/dest*` context. +- **Pre-turn requirement**: `getPreReqTurn()` uses `LastTurn` to accumulate + term stack (`addTermStack()`), logging "수행중" until the term completes. +- **Post-turn requirement**: `getPostReqTurn()` uses `next_execute` storage + (general: `next_execute`, nation: `nation_env`) to block early execution. +- **Run flow**: `run($rng)` returns `true` when completed; `false` can chain to + `getAlternativeCommand()`. + +## Turntime & Lifecycle (`updateTurnTime`) + +- **Inactivity**: if `killturn <= 0`: + - NPC-owned characters can detach (owner -> NPC) if `deadyear` not reached. + - Otherwise the general is deleted (`kill()`). +- **Retirement**: if `age >= retirementYear` and not NPC, `CheckHall()` and + `rebirth()` are invoked. +- **Scheduling**: next `turntime` is `addTurn(current, turnterm)` with + optional `nextTurnTimeBase` override (aux var). + +## Deterministic RNG Seeds + +RNG uses `LiteHashDRBG` with `UniqueConst::$hiddenSeed`: + +- Preprocess: `('preprocess', year, month, generalID)` +- Nation command: `('nationCommand', year, month, generalID, commandKey)` +- General command: `('generalCommand', year, month, generalID, commandKey)` +- Monthly: `('monthly', year, month)` + +These seeds make command outcomes and monthly updates reproducible for +validation. + +## Open Questions / Follow-ups + +- `preUpdateMonthly()`, `postUpdateMonthly()`, `turnDate()`, `checkStatistic()` + are defined outside this flow; see `legacy/hwe/func_time_event.php` for + economic updates and population calculations. +- `updateTraffic()`, `checkDelay()`, `updateOnline()` logic lives in + `legacy/hwe/func.php` and related utility files. diff --git a/docs/architecture/legacy-engine-general.md b/docs/architecture/legacy-engine-general.md new file mode 100644 index 0000000..18b3731 --- /dev/null +++ b/docs/architecture/legacy-engine-general.md @@ -0,0 +1,91 @@ +# Legacy General Model and Action Stack + +This document captures how `General` aggregates modifiers, computes stats, and +exposes trigger hooks. The main reference is `legacy/hwe/sammo/General.php`. + +## Construction and Core State + +- `General` builds from raw DB rows (general, city, nation, rank, access log). +- `last_turn` is parsed into `LastTurn`, and a separate `resultTurn` is + maintained for updates. +- `penalty` JSON is decoded into `PenaltyKey -> value` map. +- Rank data is tracked with: + - `rankVarRead` (current read view) + - `rankVarIncrease` (increment queue) + - `rankVarSet` (explicit set queue) + +## Action Objects (`iAction`) + +`General` composes action sources into a single list: + +1. Nation type (`buildNationTypeClass`) +2. Officer level (`TriggerOfficerLevel`) +3. Domestic special (`buildGeneralSpecialDomesticClass`) +4. War special (`buildGeneralSpecialWarClass`) +5. Personality (`buildPersonalityClass`) +6. Crew type (`GameUnitConst::byID`) +7. Inheritance buff (`TriggerInheritBuff`) +8. Scenario effect (`buildScenarioEffectClass`) +9. Items: horse / weapon / book / item (`buildItemClass`) + +`getActionList()` returns this merged list and is the core entry point for +modifiers and triggers. + +## Stat Computation + +`getStatValue()` applies layered modifiers: + +- Base stat from raw value +- Injury multiplier +- Cross-stat adjust (strength/intel + 1/4 of the other stat) +- Clamp to `GameConst::$maxLevel` +- `onCalcStat()` from every action object +- Cached by `(statName, injury, action, adjust)` tuple + +Convenience wrappers: +- `getLeadership()`, `getStrength()`, `getIntel()` + +## Turn Reservation and LastTurn + +- `getReservedTurn(turnIdx)` reads from `general_turn`. +- When no entry exists, `buildGeneralCommandClass(null)` creates `휴식`. +- `LastTurn` holds `{ command, arg, term, seq }` and is used by + `BaseCommand::addTermStack()` to advance multi-turn commands. +- `applyDB()` persists updated fields and writes `last_turn` if it changed. + +## Trigger and Modifier Hooks + +`General` delegates calculations and trigger lists through action objects: + +- Economy/strategy: `onCalcDomestic`, `onCalcStrategic`, + `onCalcNationalIncome` +- Combat modifiers: `onCalcStat`, `onCalcOpposeStat`, `getWarPowerMultiplier` +- Arbitrary actions: `onArbitraryAction` (used in city conquest) + +Turn-prep triggers: + +- `getPreTurnExecuteTriggerList()` merges trigger lists from every action + object. `TurnExecutionHelper::preprocessCommand()` adds + `che_부상경감` + `che_병력군량소모` on top. + +Battle triggers: + +- `getBattleInitSkillTriggerList()` merges per-action battle-init triggers. +- `getBattlePhaseSkillTriggerList()` includes base phase triggers: + - `che_필살시도`, `che_필살발동` + - `che_회피시도`, `che_회피발동` + - `che_계략시도`, `che_계략발동`, `che_계략실패` + - plus any action-specific additions. + +## Rank and Access Log Updates + +- `increaseRankVar()` / `setRankVar()` queue updates until `applyDB()`. +- `applyDB()` updates `general` and `rank_data`, then flushes logs. +- `checkStatChange()` uses `*_exp` thresholds to increase/decrease stats and + logs level changes. + +## Open Questions / Follow-ups + +- `PenaltyKey` effects and how penalties are applied are outside this file. +- `GeneralBase` and `LazyVarAndAuxUpdater` may contain additional state + conventions for new code to mirror. diff --git a/docs/architecture/legacy-engine-war.md b/docs/architecture/legacy-engine-war.md new file mode 100644 index 0000000..e59b3d5 --- /dev/null +++ b/docs/architecture/legacy-engine-war.md @@ -0,0 +1,109 @@ +# Legacy Battle and War Resolution + +This document summarizes the legacy battle pipeline centered on +`legacy/hwe/process_war.php`, `legacy/hwe/sammo/WarUnit.php`, +`legacy/hwe/sammo/WarUnitGeneral.php`, and `legacy/hwe/sammo/WarUnitCity.php`. + +## Entry Point: `processWar` + +Inputs: + +- `warSeed` (string): battle RNG seed +- `attackerGeneral`: `General` +- `rawAttackerNation`: nation row (snapshot) +- `rawDefenderCity`: city row (snapshot) + +Setup steps: + +1. Initialize RNG with `warSeed` (`LiteHashDRBG`). +2. Load defender nation row (or default neutral nation if `nation = 0`). +3. Build `WarUnitGeneral` (attacker) and `WarUnitCity` (defender city). +4. Collect defender generals in the city, filter with `extractBattleOrder()`. +5. Optionally append city as defender if city order > 0. +6. Sort defenders by battle order, iterate via `getNextDefender()`. +7. Run `processWar_NG()`; update DB and nation/city stats. + +## Battle Order (`extractBattleOrder`) + +For defender generals: + +- Must have crew > 0 +- Must have rice > crew/100 +- `train` and `atmos` must meet `defence_train` +- Battle order uses: + - `totalStat = (realStat + fullStat) / 2` + - `totalCrew = crew / 1_000_000 * (train * atmos) ^ 1.5` + - `totalStat + totalCrew / 100` + +For cities: + +- Uses attacker `onCalcOpposeStat('cityBattleOrder', -1)`. + +## Battle Loop (`processWar_NG`) + +1. Log start, include seed in battle logs. +2. If no defenders remain, set defender = city and switch to siege. +3. **Initial engagement** + - `setOppose()` for attacker/defender + - `addTrain(1)` for both + - Fire battle-init triggers +4. **Per phase** + - `beginPhase()` computes war power + - Fire battle-phase triggers + - `calcDamage()` on both sides + - Clamp damage if it exceeds HP ratios + - Apply damage, increase killed/dead counters + - Log phase results +5. **Continuation checks** + - `continueWar()` fails on no rice or HP <= 0 + - On retreat/defeat: log, apply win/lose, try wound + - If defender removed, move to next defender (or city siege) +6. **Finish** + - `logBattleResult()` for last phase if needed + - `finishBattle()` for attacker/defender + - City conflict tracking and history logs + +## Post-Battle Updates (`processWar`) + +After `processWar_NG()`: + +- Apply attacker DB updates +- Update nation rice (supply and siege rules) +- Distribute city `dead` counts (40% attacker city, 60% defender city) +- Increase nation tech based on killed/dead and nation size adjustments +- Update `diplomacy.dead` for both sides +- If city conquered: call `ConquerCity()` + +## `WarUnitGeneral` Highlights + +- Train/atmos bonuses depend on city level and attacker/defender role. +- War power: + - Base attack/defence from crew type + tech + - Adjusted by train/atmos, dex (`getDex()`), crew type coefficients + - Experience level scales war power and counter-scales opponent + - `General::getWarPowerMultiplier()` applies special multipliers +- Rice consumption on kills: proportional to damage, tech cost, unit rice +- Wound chance: 5% unless `부상무효` / `퇴각부상무효` triggered +- `finishBattle()` updates rank stats, rounds values, and checks stat changes + +## `WarUnitCity` Highlights + +- Uses `DummyGeneral` with `CREWTYPE_CASTLE` +- HP = `def * 10` +- Computed attack/defence = `(def + wall * 9) / 500 + 200` +- City train/atmos scales with elapsed years since `startYear` +- Siege state: + - Non-siege battle ends after one exchange + - Siege continues until HP <= 0 +- `heavyDecreaseWealth()` halves `agri/comm/secu` on supply-based rout +- `addConflict()` records contribution in `city.conflict` JSON + +## Deterministic RNG + +- Main battle uses `warSeed` directly. +- City conquest uses `hiddenSeed + 'ConquerCity' + year + month + nationID + generalID + cityID`. + +## Open Questions / Follow-ups + +- Detailed conquest outcomes (nation collapse, officer handling) extend beyond + the summary here; see `ConquerCity()` in `legacy/hwe/process_war.php`. diff --git a/docs/architecture/legacy-engine.md b/docs/architecture/legacy-engine.md index ce3eba9..2f1a3bc 100644 --- a/docs/architecture/legacy-engine.md +++ b/docs/architecture/legacy-engine.md @@ -34,3 +34,11 @@ organization rather than endpoint-first routing. - "attempt" then "execute" phases - Common trigger categories (traits, specials, scenario effects) - How triggers combine when multiple sources apply + +## Detailed Notes + +- Turn execution pipeline: `docs/architecture/legacy-engine-execution.md` +- General model and action stack: `docs/architecture/legacy-engine-general.md` +- Battle and war resolution: `docs/architecture/legacy-engine-war.md` +- Command catalog: `docs/architecture/legacy-commands.md` +- Scenario system and rule sets: `docs/architecture/legacy-scenarios.md` diff --git a/docs/architecture/legacy-scenarios.md b/docs/architecture/legacy-scenarios.md new file mode 100644 index 0000000..6b99716 --- /dev/null +++ b/docs/architecture/legacy-scenarios.md @@ -0,0 +1,109 @@ +# Legacy Scenario System + +This document explains how scenarios are loaded and how they define the active +rule set, commands, and effects. Core references include +`legacy/hwe/sammo/Scenario.php`, `legacy/hwe/sammo/ResetHelper.php`, and +`legacy/hwe/sammo/GameConstBase.php`. + +## Scenario Loading Flow + +1. Server reset/init calls `ResetHelper::buildScenario()`. +2. `Scenario` loads `scenario_{id}.json` and merges defaults (`default.json`). +3. `Scenario::buildConf()` generates runtime constants: + - `d_setting/GameConst.php` from `GameConstBase + scenario.const/map/stat` + - `d_setting/CityConst.php` from `scenario/map/{mapName}.php` + - `d_setting/GameUnitConst.php` from `scenario/unit/{unitSet}.php` +4. `Scenario::build()` inserts nations, generals, and events into DB and runs + `initialEvents` immediately. + +`Scenario::getAllScenarios()` is used for listing scenarios without fully +building them (lazy init). + +## Scenario JSON Structure (Observed) + +Common top-level keys (see `legacy/hwe/scenario/frame.json` and actual +`scenario_*.json` files): + +- `title`, `startYear`, `history`, `iconPath` +- `stat`: default stat totals and bounds +- `map`: `mapName`, `unitSet`, `scenarioEffect` +- `const`: overrides for `GameConst` (commands, items, limits, etc.) +- `nation`, `diplomacy` +- `general`, `general_ex`, `general_neutral` +- `events`, `initialEvents` +- `ignoreDefaultEvents` (skip `GameConst::$defaultInitialEvents/$defaultEvents`) + +Notes: + +- A few files still use `initialActions` or `defaultInitialEvents` keys. The + engine currently reads `initialEvents` only. +- `general` rows use the tuple format from `Scenario::generateGeneral()`: + `affinity, name, picture, nationName, city, leadership, strength, intel, + officerLevel, birth, death, ego, char, text`. + +## How Scenario Chooses Commands and Effects + +Scenario config influences runtime rules via `GameConst` and `ScenarioEffect`: + +- `const.availableGeneralCommand` / `const.availableChiefCommand` define the + commands that appear in UI and can be executed. +- `const.availableSpecialDomestic/War`, `const.availablePersonality`, + `const.allItems`, `const.availableNationType` control selectable traits/items. +- `map.scenarioEffect` or `const.scenarioEffect` sets + `GameConst::$scenarioEffect`, which is injected into each `General` as an + `iAction` (`General::getActionList()`). +- `const.availableInstantAction` merges into + `GameConst::$availableInstantAction`. + +Because `GameConst` is generated from scenario data, a scenario can swap +available commands or replace the action pool entirely. + +## Command Prefix Conventions + +Prefixes are used to separate rule packs and assets: + +- `che_`: default rule set (base commands, specials, items, nation types). +- `cr_`: alternate rule set used by specific scenarios (e.g. `scenario_910`). +- `event_`: scenario-specific extensions (research, extra unit sets, or special + effects). + +Example: `scenario_910.json` uses `mapName=cr` and `unitSet=cr` and overrides +`availableGeneralCommand/availableChiefCommand` to include `cr_건국`, +`cr_맹훈련`, and `cr_인구이동` alongside `che_` commands. + +## Scenario Environment Variants (Current Repo) + +These are the map/unit/effect variants referenced by existing scenario files. +Defaults are `mapName=che` and `unitSet=che` when not specified. + +Map sets (`scenario/map/*.php`): +- `che` (default) +- `miniche`, `miniche_b`, `miniche_clean` +- `cr` +- `chess` +- `pokemon_v1` +- `ludo_rathowm` + +Unit sets (`scenario/unit/*.php`): +- `che` (default) +- `che_except_siege` +- `cr` +- `basic` +- `siegetank` +- `event_more_crewtype` +- `ludo_rathowm` + +Scenario effects (`sammo/ActionScenarioEffect/*`): +- `event_StrongAttacker` +- `event_UnlimitedDefenceThresholdChange` +- `event_MoreEffect` + +## Event Targets + +Scenario events are stored in the `event` table and executed via +`TurnExecutionHelper::runEventHandler()` using `EventTarget` values: +`PRE_MONTH`, `MONTH`, `OCCUPY_CITY`, `DESTROY_NATION`, `UNITED`. + +Most scenario JSON uses lowercase targets (e.g. `"month"`). The DB enum uses +uppercase values but is case-insensitive, so lowercase targets still match. + diff --git a/docs/architecture/todo.md b/docs/architecture/todo.md index fab775e..99c6e24 100644 --- a/docs/architecture/todo.md +++ b/docs/architecture/todo.md @@ -28,3 +28,9 @@ Move items into the main docs once they are finalized. - "Next-turn intent" (예턴) data schema and lifecycle - Profile selection workflow and deployment mapping + +## Legacy Engine Docs + +- [AI suggestion] Expand monthly pipeline details (`preUpdateMonthly`, `postUpdateMonthly`, `turnDate`, `checkStatistic`) with concrete side effects and tables touched. +- [AI suggestion] Document `ConquerCity()` resolution paths (nation collapse, officer handling, reward/penalty rules). +- [AI suggestion] Clarify command prefix semantics (`che_`, `cr_`, `event_`) and add per-command effect summaries.