7.2 KiB
Legacy General AI (GeneralAI)
This document summarizes how legacy/hwe/sammo/GeneralAI.php selects nation and
general commands, which data fields it relies on, and how policies shape NPC
behavior. It also outlines considerations for an in-memory rewrite of the AI
loop.
Entry Points
chooseNationTurn(NationCommand $reservedCommand)chooseInstantNationTurn(NationCommand $reservedCommand)chooseGeneralTurn(GeneralCommand $reservedCommand)
All three call updateInstance() first, which caches current state and derives
key AI decisions (diplomacy state, general type, policy setup).
Deterministic RNG
GeneralAI uses LiteHashDRBG seeded with:
hiddenSeed + "GeneralAI" + year + month + generalID
This makes AI choices reproducible per turn. All random choices (choice,
choiceUsingWeight, nextBool) flow through this RNG.
State Snapshot and Derived Fields
updateInstance() pulls and caches:
game_env(viaKVStorage): year, month, startyear, turnterm, develcost, init_year/init_month, killturn, global NPC policy defaults.city(current city row, fromgeneral->city).nation(nation row, or fallback for neutral).nation_env(KVStorage): npc policy overrides, prev income, last attackable.nation['aux']decoded JSON.generalprimary stats (leadership/strength/intel; both full and adjusted).baseDevelCostandmaxResourceActionAmount.dipState,attackable,warTargetNation.genType(type flags derived from stats + policy thresholds).
Derived groupings are computed lazily:
categorizeNationCities()=>nationCities,frontCities,supplyCities,backupCitieswith per-citydevandimportantscores.categorizeNationGeneral()=> user/NPC buckets, war/civil buckets, troop leaders, lost generals, chief list.
Diplomacy State (calcDiplomacyState)
Diplomacy state controls war/peace behavior:
d평화: no war declarations, no active war.d선포: declaration in progress, no active war.d징병: pre-war recruitment window.d직전: immediate pre-war.d전쟁: active war, or recently lost a front (grace period).
Key inputs:
diplomacyrows (state,term) for current nation.frontcities withsupply=1.year/monthrelative tostartyear(early-game war lockout).
warTargetNation tracks eligible enemies:
2= currently at war.1= declaration in progress / pre-war.0is used as "any neighbor" fallback when no active target exists.
General Type (calcGenType)
General type is a bitmask:
t무장(strength-leaning)t지장(intelligence-leaning)t통솔장(leadership threshold for war-capable NPCs)
Logic:
- Strength vs intel decides initial bias.
- If the weaker stat is within 80%, a probabilistic hybrid type can be added.
t통솔장is set whenleadership >= nationPolicy->minNPCWarLeadership.
Policy Inputs (Autorun)
AutorunNationPolicy and AutorunGeneralPolicy are built from:
- per-user autorun options (
env['autorun_user']['options']) nation_envoverrides (npc_nation_policy,npc_general_policy)- global defaults (
env['npc_nation_policy'],env['npc_general_policy']) - live nation + env snapshot
Policies provide:
priorityaction listscan{Action}toggles- thresholds (min crew, safe population ratio, resource floors, etc.)
Nation Turn Behavior (chooseNationTurn)
Nation-level choices run only for NPCs (npc >= 2) or for autorun users:
- Apply quarterly promotions and tax/bill adjustments.
- Honor reserved nation commands if valid.
- Iterate policy
priority, invoking matchingdo{Action}. - Fall back to neutral (empty) nation command if all fail.
Major Action Groups
- Troop movement
do부대전방발령,do부대후방발령,do부대구출발령- user/NPC versions to move generals between front/back/supply cities
- checks
frontCities,supplyCities,last발령, and war route.
- Resource distribution
do유저장포상,doNPC포상,doNPC몰수- uses resource floors (
reqNation*,reqNPC*,reqHuman*) - weighted by target general's deficit and recent activity.
- Diplomacy
do불가침제의: respond to assistance requests with NAP offer.do선전포고: probabilistic declaration when strong enough.
- Capital relocation
do천도: moves capital based on population, dev, and connectivity.
General Turn Behavior (chooseGeneralTurn)
General-level decisions are layered:
- NPC message broadcast if
npcmsgand RNG triggers. - Reserved command is honored if valid (unless
휴식). - Immediate recovery if
injury > cureThreshold. - Special cases:
- NPC troop leaders (type 5) always
집합. - wanderers decide on founding / moving / disbanding.
- NPC troop leaders (type 5) always
- Iterate policy
priority, invokingdo{Action}. - Fallback to
do중립.
Major Action Groups
- Domestic development
do일반내정,do전쟁내정,do긴급내정- weighted by
citydev rates and general type flags.
- War preparation
do징병,do전투준비,do출병- strict checks on crew, train, atmos, population and diplomacy state.
- Mobility
do전방워프,do후방워프,do내정워프,do귀환- uses
front/supply/backupcities and population thresholds.
- Resource handling
do금쌀구매(trade),doNPC헌납(donation).
- Neutral behavior
do중립selects between물자조달,인재탐색,견문.
Data Fields Accessed (Representative)
GeneralAI reads or writes:
- Nation:
nation,capital,gold,rice,tech,level,type,chief_set,rate,bill,aux. - City:
city,nation,supply,front,pop,pop_max,trust,agri/comm/secu/def/walland*_max,trade,level,region. - General:
npc,officer_level,officer_city,killturn,injury,troop,crew,train,atmos,defence_train,gold,rice,belong,permission,npcmsg,dex1..dex5,armType,affinity,makelimit. - KVStorage:
npc_*_policy,prev_income_*,last_attackable,last천도Trial,resp_assist*.
In-Memory Rewrite Considerations
To port the AI to an in-memory state model without behavior drift:
- Snapshot-first
- Build a per-turn
GameSnapshotcontaining env, nation, cities, generals, diplomacy, and nation_env.GeneralAIshould read only from this snapshot.
- Build a per-turn
- Derived caches
- Cache
DiplomacyState,CityBuckets,GeneralBuckets, andWarRoute. - Use lazy recalculation and invalidate only the affected region/city/general after a command is applied.
- Cache
- Deterministic ordering
- For candidate lists, sort by ID before weighted RNG to preserve parity.
- RNG seeding should keep the exact per-turn seed scheme to ensure replay.
- Command evaluation
- Keep
hasFullConditionMet()semantics intact by providing the same generalized context (general,city,nation,dest*).
- Keep
- Policy snapshots
- Cache policy values per turn and avoid reading KVStorage per action.
- When policies change, treat it as an explicit state transition.
These guidelines mirror the current "derive once, then select via priority" pattern and minimize resimulation deltas in the rewrite.