I agree, the throne room looks like someone stacked up tables behind Lord British.
I was planning to add an ankh tile similar to this:
which is the throne room in Ultima IV.
Yesterday I found the tables with enemy encounters, the spellcasting routines, and the routines used to generate pseudo-random numbers.
I think I will fix the "Repel" and "Undead" spells next.
They have two main issues:
- Each can only be used against two types of enemies only, which are mostly encountered at lower levels.
Basically the spells are overpowered at lower levels, then become a waste of space in the magic menu.
- They are supposed to be random, to offset the fact that they cost no MP, but they don't use the RNG routines.
Instead they do an AND with a counter which is incremented once per vblank. The result is well known: this can be exploited to time the button press with the sprite animations and make the spell 100% successful.
So my plan for today is:
- Change the spell so that it can still one-hit kill low level monsters, but it can also do some damage to other types of enemies found at higher levels.
- Make both spells cost at least a bit of MP.
- Make either the success chance or effectiveness based on caster level and stats (INT for Repel, WIS for Undead).
This is going to take some extra space in ROM, but there should be enough at the end of the same bank where the spellcasting routines are.
I've been looking into the "battle AI" routine, and it seems that the enemy's ability to attack diagonally is either unintended or the result of the developers running out of space in the last bank for a complete implementation.
Some values are written during enemy movement but never read, and the routine that decides if a target is in range only reads the sum of the X and Y distances.
Since bank #0 is already loaded when the evaluation happens, and that has relatively abundant free space, I may just write the extra battle AI there.
Or I may get rid of the code that allows enemies to steal stuff from the player (which is just annoying since stolen items can't be recovered or looted) and use that space instead...
In the meanwhile I found where the game stores NPC data for the current map, including the encoded address of the pattern for their sprites.
So here is Chuckles, restored to his normal clothes (I guess he was turned into a woman by mistake):
Now I just need to find where is the routine that reads that data from ROM.
After further examination, the enemy's diagonal attack may have been left there intentionally.
In its absence, some really cheap tactics are possible: moving a character constantly left and right, enemies can never attack, other player characters can safely kill it with ranged attacks/magic.
Anyway, the distances are recalculated several times instead of using previously stored values, so I'll use that to speed up this routine a bit.
I've also found where the NPC data tables are stored for each location. I can permanently change Chuckles and see if there is room for extra features like NPC names/portraits etc.
The town and world maps are stored in a very simple way, "packed" so that each byte represents two tiles.
4 bits per tile means only 16 tiles are available to use without drastically changing the map system.
In towns, there are two values that are never used, so I can add an Ankh tile as planned, and have space left for one alternative grass tile.
In the "overworld" maps there is some more room, might be worth adding more grass tiles since that's what most of the map is made of.