# 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()`. 9. **LastTurn persistence** - General `LastTurn` lives in `general.last_turn` JSON. - Nation `LastTurn` is stored in `nation_env` under `turn_last_{officer_level}`. - `LastTurn.term` only advances when the same command + arg repeats across turns. ## 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). ## killturn, block, autorun - `killturn` acts as an inactivity counter; it is reset to `game_env.killturn` when a non-rest player action completes, and decremented for NPCs, autorun, rest commands, or block states. - `block >= 2` forces `killturn` decrement and logs a block message. - When `killturn <= 0`, the general is converted to NPC (owner removed) or deleted depending on NPC type and `deadyear`. - `autorun_limit` is stored in general `aux` and used to decide AI takeover. ## 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.