AI nobles — Lords of the Realm 2#
Behavioral reference for the four computer-controlled claimants to the throne. Use this when implementing campaign AI, diplomacy UI, and the Great Noble ranking screen in a clean-room client (e.g. Phaser).
Normative gameplay rules belong in docs/spec/ eventually; this tree
is evidence-backed design reference with confidence labels.
Who they are#
After the king dies, up to five lords compete for the crown. In single player, four fixed AI personalities oppose the human player:
| Directory | culture_row |
Display name (L2.ENG group 7) |
|---|---|---|
| Knight | 1 | The Knight |
| Baron | 2 | The Baron |
| Countess | 3 | The Countess |
| Bishop | 4 | The Bishop |
The human player is not a fixed character. At wizard setup they pick a
faction color (1–5) and enter a custom name (or keep the default from
group 7 once a culture_row is assigned). See Assignment below.
Character flavor text comes from the Sierra manual (diplomacy section, pp. 97–100).
Mechanics come from retail LORDS2.EXE and L2.ENG.
Assignment#
At campaign start, lotr2_game_ai_assign_nation_culture_slots assigns each active
AI slot a unique culture_row (1–4) and copies the matching L2.ENG group-7 name
into the player name block.
- For each player slot 1..5 that is active and not eliminated, pick the next
unused
culture_rowfrom a per-color shuffle table @0x004f7c84. lotr2_game_ui_eng_seek_entry(7, culture_row)→ copy 16 bytes todisplay_name@0x0055a904 + slot * 0x2c.- Text colors @
+0x55ada8/+0x55ada9from0x004f7cd6[faction_color * 2].
Culture assignment table (retail bin/LORDS2.EXE, first four bytes per color):
| Faction color | Assignment order (culture_rows) |
|---|---|
| 1 | 2, 1, 3, 4 |
| 2 | 1, 3, 4, 2 |
| 3 | 2, 1, 3, 4 |
| 4 | 4, 3, 2, 1 |
| 5 | 3, 2, 4, 1 |
So the same faction color does not always map to the same noble; the table only defines which archetype fills which slot when multiple AIs join.
Multiplayer: up to five human players choose colors; AI fills empty slots using
the same assignment pass (DAT_0059b888 controls how many AI slots activate).
Data model#
Player runtime record: stride 0x160, documented in
lotr2_player_record.md.
Key field: culture_row (+0x03) → indexes all per-noble AI tables via
(culture_row * 3 - 3) * 0x50.
Display names: separate array @ 0x0055a904, stride 0x2c (44 bytes).
AI parameter tables#
All values below are confirmed from retail bin/LORDS2.EXE (regenerate with
python3 tools/ghidra/dump_noble_tables.py). GoG Lords2.exe uses different
data VAs — do not copy these addresses into the GoG export without re-dumping.
| Parameter | Knight (1) | Baron (2) | Countess (3) | Bishop (4) |
|---|---|---|---|---|
pop_bonus_type |
2 | 2 | 2 | 1 |
attack_patience |
3 | 4 | 4 | 2 |
attack_gold_budget |
750 | 800 | 900 | 1000 |
defender_spawn_count |
30 | 30 | 40 | 50 |
desperation_threshold |
100 | 120 | 200 | 250 |
gold_buy_threshold |
1000 | 1500 | 2500 | 4000 |
gold_buy_amount |
100 | 80 | 70 | 150 |
troop_sword_threshold |
250 | 300 | 500 | 1000 |
troop_pike_threshold |
250 | 300 | 500 | 1000 |
troop_bow_threshold |
250 | 300 | 500 | 1000 |
Note: desperation_threshold first dword in block; Countess uses +100 build
budget when triggered (lotr2_game_ai_apply_desperation_bonuses), Bishop +100
to two stockpile fields. Knight and Baron get no special desperation bonus.
Score bonuses (turn income when popularity tier < 3)#
Low popularity @ 0x004f7d38 — four map-size rows per culture_row:
| Noble | Row values |
|---|---|
| Knight | 0, 160, 250, 400 |
| Baron | 40, 180, 300, 500 |
| Countess | 0, 160, 250, 400 |
| Bishop | 100, 240, 400, 600 |
High popularity @ 0x004f7ce8:
| Noble | Row values |
|---|---|
| Knight | 0, 400, 700, 1200 |
| Baron | 100, 500, 800, 1400 |
| Countess | 0, 400, 700, 1200 |
| Bishop | 250, 600, 1100, 1800 |
Great Noble screen#
Shown from diplomacy flow via lotr2_game_ui_enter_great_noble_screen:
flowchart TD
enter["enter_great_noble_screen"]
assets["Load grtnoble.256 + grtnoble.pl8 + flags.pl8"]
pick["great_noble_pick_leader: max stat per column"]
bars["For each active player: bar height = (100 - pct) * 2"]
label["Draw L2.ENG group 0x23 label for stat column"]
leader["If tie: undecided; else show leader name"]
enter --> assets --> pick --> bars --> label --> leader
Stat column labels (L2.ENG group 0x23 / 35):
| Index | Label |
|---|---|
| 0 | Most counties |
| 1 | Most castles |
| 2 | Most troops |
| 3 | Most crowns |
| 4 | Happiest people |
| 5 | Most people |
| 6 | Greatest noble |
| 7 | undecided. |
lotr2_game_ui_great_noble_stat_value(player_id) reads the player field for the
current column (DAT_00583108). Bars are normalized against the leader’s value
via lotr2_game_ratio_percent.
Phaser notes
- Background:
grtnoble.pl8+ palettegrtnoble.256(480px-wide screen mode). - Portrait per player: PL8 frame
culture_row + 9(wizard roster convention). - Flag icon: frame
culture_row * 3 - 3(0, 3, 6, 9 for rows 1–4). - Leader name:
display_namestring; tie → group 0x23 entry 7.
Display names (L2.ENG)#
Noble names are not embedded in the EXE. They live in L2.ENG
group 7:
| Index | String |
|---|---|
| 0 | No player |
| 1 | The Knight |
| 2 | The Baron |
| 3 | The Countess |
| 4 | The Bishop |
Parser: tools/parse_l2_eng.py.
Multiplayer team epithets (Lions, Dragons, …) are group 88 and bind to
faction color, not culture_row.
Per-noble pages#
| Noble | Summary |
|---|---|
| Knight | Aggressive, poor economist; attacks early; low patience |
| Baron | Defensive economist; highest attack patience; oppressive rule |
| Countess | Balanced expansion; build boost when desperate |
| Bishop | Castle-heavy, high thresholds; ruthless diplomacy edge case |
Evidence index#
| Layer | Path |
|---|---|
| Decompilation | src/LORDS2.EXE.c |
| Struct | lotr2_player_record.md |
| Game module | architecture/game/MODULE.md |
| Assets | architecture/asset/MODULE.md (grtnoble.pl8) |
| Dump tool | tools/ghidra/dump_noble_tables.py |
Open questions#
- Exact troop-mix weights per noble (partially described in manual only)
- Full desperation / attack state machine (14-step AI loop)
- GoG binary table addresses and parity with retail values