Wednesday 14 December 2022

Xevious reveals all its secrets.

I've spent the last few sessions trying to finish off the RE and the missing pieces of the AI puzzle.

As a result, the SUB CPU ROM is now 100% complete. All the variables related to the game logic have been understood, named and the routines documented. I could probably spend an hour or so just tidying things up, adding a bit more annotation, but it's essentially done.

Correspondingly, the MAIN CPU ROM is all-but-complete. I haven't actually gone through the disassembly with a fine-tooth comb just yet, but the only missing annotations should be the miscellaneous housekeeping such as score and bonus updates. If I had to guess, I'd say it's 95% complete now.

As for what I've loosely referred to as 'AI' - for want of a better (more concise) term - I believe I've now RE'd all the logic that controls the difficulty of the game. It's not quite as complex as the advertisements suggested back in the day, and I wonder if plenty of other games don't have similar logic built in?!?

At the core of the logic is a couple of tables. First is a table that contains pairs denoting the number of flying enemies and an offset into a 2nd table. That second table is a list of enemy types in (roughly) increasing order of difficulty. So Toroids tend to appear first, with Zoshis and Brag Zakatos appearing later.

The map data contains a 'place holder' object that indexes into the 1st table; for example it may specify 3 Toroids. However there is another variable that is added to the index read from the 1st table, and used for the 2nd table - that variable is what I've named enemy_AI_level. This variable starts out at 0, and is incremented throughout the game - the effect being that the latter index gets larger and larger, causing more potent enemies to appear.

The enemy_AI_level is increased using a few different mechanisms:

  • decremented at the start of each new Solvalou according to the STARTING LIVES dipswitch setting
  • incremented explicitly in the map data accoring to the DIFFICULTY dipswitch setting
  • incremented explicitly in the map data depending on the current score
Incidentally, the enemy_AI_level is decreased by 2 each time a Zolbak is destroyed.

The adjustment depending on the current score is interesting; the amount of adjustment is calculated by dividing the current score (in thousands) by the number of Solvalou that have been used thus far. IOW the average score per Solvalou for the current game. The adjustment factor is (seemingly) equal to the thousands of points scored per Solvalou, with an upper limit of 16, so if you average more than 10,000* points per Solvalou - which is pretty easy for a seasoned player - then the game will play at effective maximum difficulty for that dipswitch setting.

[* Technically the score is represented in BCD, whilst the division operates as if it were in binary. 9,000 points on 1 Solvalou ($09/1) results in an increment of 9, whilst 10,000 points ($10/1) results in an increment of 16. Confusing, but there's still a monotonic increase.]

The other piece of RE I finished today was the Bacura, which operate with their own set of variables, not affected by the enemy_AI_level but rather explicit values in the map data. I'm yet to implement any of the Bacura logic in the transcode; that's next!

Once I finish the Bacura code and debug a few minor issues in the flying enemies, it'll be a case of implementing the destruction of both flying enemies and the Solvalou, and then tidying up all the remaining housekeeping functions. Probably a week or so there, but I'm fast running out of time for the year.

The final stage (before sound) is then optimising the Neo Geo code, and getting it running at 100% on my real AES hardware!

UPDATE: enemy_AI_level is reduced at the start of each Solvalou, not adjusted at the start of each area.

No comments:

Post a Comment