Skip to content

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.

  1. For each player slot 1..5 that is active and not eliminated, pick the next unused culture_row from a per-color shuffle table @ 0x004f7c84.
  2. lotr2_game_ui_eng_seek_entry(7, culture_row) → copy 16 bytes to display_name @ 0x0055a904 + slot * 0x2c.
  3. Text colors @ +0x55ada8/+0x55ada9 from 0x004f7cd6[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 + palette grtnoble.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_name string; 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