[FE7] The Official AI Documentation Thread

Just as an addendum…it turns out a Shade/Provoke mechanic would be very easily implementable in the current engine; the routine at $08039138 loops through some fixed locations in ROM (pointers at $8B970C8) and compares each byte there with the target’s class ID; the function returns the loop counter upon finding a match with this ID or going through 0x9 entries (each entry is terminated by a 0x0 byte).

By default the list it looks at is filled up with zeroes, so this function always returns 0x9. Then the game multiplies TP_modifier[0x3] by TP_modifier[0x8+return value], and adds that (max value of 20 by default) to the total TP for that target.

In the unmodified ROM this always ends up being 0x0; but by modifying the TP modifier struct and the list that checks for class bytes, one could make it so that certain classes have a higher or lower priority than normal.

More TP routines:
$0803916C - multiplies the current turn number by TP_modifier[0x4], and adds the result to the total TP.

$08039184 - If the target has no weapon it can use, add 10 to the total TP. Otherwise, calculate the target’s projected damage from a counter (accounting for hit%) and multiply by TP_modifier[0x5].

If penalty > 0x28 (50), set to 0x28. Subtract penalty from the total TP so far.

$0803921C - Multiply (20-Attacker’s HP after a successful counter) by TP_modifier[0x7]. Subtract this return value from the total TP so far.

The remaining routines that modify TP are at $080391E4 (calcs a penalty) and $08039094 (calcs a bonus) - they seem to have something to do with map data, and the attacker’s allegiance.

2 Likes
08037928 F7EBFFC2 bl      #0x80238B0

This is the allegiance check. It take two characters’ deployment numbers in r0 and r1 and returns true if they ARE on the same side. This is what makes Other units friendly(the stat of their 0x80 bit is the same as players) and hypothetically, player 4 units are allied with enemies.

… also, we can totally jack this in Blazing Renaissance to make 3 way fights.

edit: funfact - we can’t process -mag/2 range weapons! idk if the player/engine still can, but the enemy is certainly incapable.

3 Likes

Would we be able to make some sort of assembly hack to change this such that it is enabled/disabled for certain chapters? :smiley:

Easily :wink:

@Agro, @Brendor. I literally changed 1 bit (made a 0x80 into 0xC0) to make it treat all factions like its own team. I’m unloading a demo to youtube shortly.

And, I realllly need help here. What does the memory at 0x202E3E4 and 0x202E3E8 store? @CT075, @Venno? Can you help me track down what writes to it and what data that is?

1 Like

Try setting a break on read and see what you get

0x0202E3D8 - X and Y size of map, used for bounding the cursor, stored here as two halfwords

It’s a bit past that.

0x0202E3E0 - Points to pointers detailed below (except for first) (not in order)
E4 -> pointer to terrain, E8 -> pointer to fog
0x0202E3F8 - Row pointers for unit map (byte per tile with value == byte at +0x0B in unit struct)

–Hextator’s doc

Newest tech demo.

2 Likes

Wait. That stuff about map data in memory isn’t matching up with what I am seeing?

0202E3DC (row pointers at 0202E400) : Location of units

0202E3E0 (row pointers at 0202EBB8) : Terrain data

0202E3E4 (row pointers at 03000448) : Movement range of selected unit
Numbers indicate amount of movement points needed to reach space from starting position. FF = cannot enter space

0202E3E8 (row pointers at 03000C00) : Related to attack/staff range of selected unit

When unit is selected: Numbers decrease as distance from unit increases. 00 = appears to be space outside of attack range. Numbers are higher when the unit has a 1-2 range weapon in inventory compared to when the unit only has 1 range weapons.

After unit moves and the attack/staff option is available: 01 = spaces that be targeted (highlighted red/green)

0202E3EC (row pointers at 0202F370) : Shaded tiles for fog-of-war and magic sealing
00 = Shaded. Greater than 00 = Clear

0202E3F0 (row pointers at 0202FB28) : Hidden fog-of-war enemies and mines
00 = None, 01 = Hidden “enemy” (display “!” and stop movement if player unit tries to enter), 02 = Mine

0202E3F4 (row pointers at 020302E0) : ???
Player Phase: Data changes whenever the movement arrow path has to be altered due to moving cursor over enemies or certain terrain.
Enemy Phase: ???

It means it’s a pointer to the row pointers of terrain data.
Terrain** val = 0x202E3E0, if you will.

Yeah, I understand the pointer to row pointers thing.

This post seems to imply:
0202E3E4 = Pointer to row pointers of terrain data
0202E3E8 = Pointer to row pointers of fog-of-war data

But when I look into memory:
0202E3E4 = Pointer to row pointers of movement range data
0202E3E8 = Pointer to row pointers of attack/staff range data

That’s interesting. Thanks, I’ll keep that in mind.

In addition of being the “defender can’t counter” bonus, this 10 TP bonus is also applied if the defender’s weapon can break during/after combat (assumes all attacks from defender will hit)

Enemy has 5/20 HP. Player unit has an Iron Sword with 2 uses left and can double attack at 5 damage per hit.
In this scenario, the unit does not get the break bonus. Although the unit can double, only 1 attack is needed to end the battle.


More detail on status staff AI:
Units need to meet a minimum hit requirement in order to be targeted by a status staff. The enemy needs 5+ hit with staff accuracy being calculated from the enemy’s start-of-phase position. The initial enemy position is used even if the enemy must move forward to get the target within staff range.

Also, enemies with status staves will retreat a few spaces if a player unit is close, so a status staff can be used at 0-4 hit as long as the 5+ hit test is passed.


Wonder why the FE7 TP mod table has values for class bonus TP even though no classes are defined? It’s because the entire TP mod table is copy-n-pasted from FE6 which actually does make use of the class bonuses.

FE6 TP mod table: 0810D728
Pointers to class sets: 085C8674

The most common class bonuses in FE6 are:
Unpromoted Lord: 10 TP
Thief M, Thief F, Bard, Dancer: 15 TP
All magic classes except Priest, Cleric, Troubadour: 5 TP

FE8 also uses the same exact table, and like FE7, doesn’t have any classes set to get bonuses.

FE8 TP mod table: 080D8178
Pointers to class sets (all point to 00): 085A8150

Can I clarify exactly what it is that these AI settings do? I tried to set these to an enemy character so that a bunch of generics would follow that enemy character around and it doesn’t seem to work. Am I misreading something or does this only work for player units? The 0x0D AI works just fine in that those units will rotate between getting units in range and going back to the designated unit, but 0x21 and 0x22 don’t seem to do… anything? They work if I set the character specified to a player character, but not an enemy.

I don’t even know if there are that many AI slots. it might be running into some other data(maybe).

Well, there’s definitely data at that table to suggest that the AI actually exists… it just doesn’t seem to do as Gryz says it does.

Fixed

1 Like

Wait a minute…

@Agro  Can you go into more detail? Because I can get an enemy to move towards another enemy by using 0x21 and 0x22 for second AI byte.

After some more testing I realised that the units with 0x21/0x22 will only move if the character they’re set to follow is outside of their attacking range… Silly me, I guess?

Yeah, 0x0D-0x11 and 0x21/0x22 should both be the same in that aspect - the difference is what the unit does once it has the target inside its range. (I should have made that clearer in the original description)

Also, I encountered something a bit strange…
I gave a bunch of enemies 0x22 AI and assigned an enemy target, but on some turns a few units wouldn’t move towards their target. Luckily, it looks like you can avoid this issue by having the enemy to be followed defined before the followers in the chapter enemy data. (And I guess it makes sense for the leader to move before the followers anyways)