Strange day today. Not just because it would have been Mike’s birthday, but because for some reason I found myself fixing a bug in Doomdark’s Revenge. Back in January I had a bug reported to me by Simon Foston, I managed to get some save games from him and just needed to find some time to look at it. Now, it’s taken a little while for me to find that time, but for some reason I looked at it today. It wasn’t a conscious decision, I was just looking through some emails that needed dealing with and noticed Simon’s bug report.
A quick look through the code and with a tip off from Simon’s report, it became apparent that the ghosts of dead lords were continuing to take part in battles. I checked the original code and it looked as if the bug was there too, however, I then found that the isDead check was happening later in the process. Strangely what it means is that battles at a dead lords location are processed as part of a dead characters turn, and not as part of other characters in the location. In my case, I’d missed the later isDead check and therefore the dead lord actually took part in the battle.
So, it seemed strange to be working on a bug in Doomdark’s Revenge that included the dearly departed, today of all days. I’m sure Mike had a wry smile..
I’ve spent some more time looking at the AI for Doomdark’s Revenge, trying to work out why it doesn’t quite appear to be playing like the original. One thing I noticed is that I have completely misunderstood the recruiting logic when it comes to Loyalty and Treachery. I made changes in the last version, but I am going to need to revert them.
The approach algorithm
compare the the attributes of the lords and looking for matches gain +1 for each match.
If the character being approached is not loyal then +1
If the character being approached is treacherous then * 2
if the recruiting character is the liege of the character being approached then +3
If the recruiting character carries a crown of persuasion then +2
If the score is greater than 3 then the approach will succeed.
The basic concept that I have misunderstood is: Loyal characters are less likely to be recruited away form their current liege and un-loyal characters are more likely, therefore the algorithm gets a +1 for none loyal characters. And that treacherous characters are more likely to leave and thus the *2
The next thing I have missed is the lords following the objectives of their lieges.
It works like this.
If the lord has a liege and that liege is following their liege or their foe, then we must follow our liege. Otherwise pick a new objective.
There is a 32% chance that we will pick a new objective. Although that should be 25% because we could pick the objective we already have. That leaves a 68%/75% chance that we continue doing what they were already doing.
The problem for me is the first check. If we use Shareth as an example. She has a 12.5% chance that she will choose to follow either her foe or leader. As she has no leader she reverts to Luxor, which is her foe. So she has a 12.5% chance that she will follow Luxor. All the lords that follow her now have a 100% chance of following Shareth, and this ripples all the way down the stack of lords. Which at the start of the game means that 47 Icelords will disregard what they are doing and follow her.
The mistake I had made is that I had made the following lords take the objectives of their liege when their liege was following their liege or foe. What this means is that when the liege is following their foe the lord follows their own foe. So using Shareth again as the example, when she is following her liege ( Luxor by default ) then all her minions will head to her location, but when she is following her foe ( Luxor ), then all her minions are heading to their foe and not to her location. So as an example, Imgaril the Icelord would be heading to Imgorthand the Fey, who, is likely the the other direction of Shareth.
Hopefully this fix should make the game more like the original, but it bothers me that it is a flawed AI. I ran the game for the first ten days, up until the first battle took place, I ran it on the emulator too to compare notes. Here is what Shareth did over those days.
Search for object
Now Talormane does this
Search for object
Search for object
The reason for the delayed follow on day 4 is because Talormane is following Lorelorn who is following Shareth, but Lorelorn is lower in the processing order than Talormane, and thus Talormane doesn’t know that Lorelorn is going to follow Shareth in that turn.
The final thing that I changed was that there is a 6.25% chance that the change of objective will be DO NOTHING. This is especially important for being in a battle with someone who is not the lords foe, because it means that without this the lord will always leave the battlefield. The mistake I had made was that I persisted the do nothing as an objective, i.e.. The lords objective becomes do nothing. But it shouldn’t, it should stay the same as the previous objective, and this turn that objective is ignored.
Going back to Shareth. If she chose to DO NOTHING then her objective would no longer be follow liege or foe, which means that her followers would be able to perform whichever objective they chose. However, if her previous objective had have been follow liege or foe, then her followers should still be heading towards her when she chooses to do nothing. This would have the affect of allowing them to catch up on her.
I have just pushed a new version of Doomdark’s Revenge out for ALL platforms. This brings all platforms in line with each other. The previous update was only released for Android and iOS. I apologiss for the delay in getting the last two versions out, but my heart and mind has just not been in it for the last couple of months.
Hopefully this will fix the remaining issues with the gameplay, and will also be the last of the 1.3 changes. The intention is that any update to follow will include some new features.
The Windows and Mac version should be showing up on your main menu now. Android/Amazon version should be ready now, or very soon. Mac App Store and iOS version will take a week in Apple Clearance, and Blackberry version usually takes a couple of days.
The changes are..
1. Fix recruitment check. Loyalty of character being approached now correctly gives +1 and when the lord is treacherous the chance of recruitment is halved – This fix should mean that treacherous lords are no harder to recruit for AI lords, which should stop lords swapping allegiance so much. They should therefore be able to focus on the task at hand.
1. Morkin’s AI attribute is reset once recruited. Stops him moving and allows him to move in tunnels. Previously Morkin’s AI attribute remained set after Tarithel recruited him. This mean that he didn’t work in tunnels very well, and had a habit of wandering off at night.
2. Tarithel can no longer be recruited away. Tarithel was incorrectly being recruited by AI lords.
3. Spell of Carudrium now works correctly. Previously this was bringing ALL characters to the location of the caster, and not just the the lords loyal to the Moonprince.
If the AI characters are still not behaving like the original, I am going to have to spend a lot more time analysing why. I can’t see any reason why the logic should not play out the same as the original ( other than the difference in random numbers ). This will involved a lot of debugging. But hopefully this version should just nudge everything in the right direction.
I’ve had a torrid few days with the updates. Only myself to blame really. I managed to release, not one, but two updates with debug code left in. Rookie mistakes! I must be more strict with the regression testing and debug development. But it’s difficult when you are working alone and trying to react as quick as possible to issues raised. This has not been made any easier by working in a Hotel where the internet access doesn’t really get going until after Midnight. Pushing out an update involves building ten different versions, and uploading ~300mb – tethering on my phone has taken a battering and my Data Plan has been boosted once already.
For the record, and just in case you have updated during that time, the two issues are; Approach will always succeed, no matter who you are or who you approach, and after attacking a stronghold, the next morning your lords will seem to have scattered. If you see this happen, you need the latest update.
iOS and OSX App Store will not have these issues as the releases had not made their way through the original update process. If you have updated Windows or Mac through the game menu, you might want to check again.
Anyway I am hoping that the latest update 1.3.4 will settle and I can take a break.
Version 1.3 has now been pushed out on all formats. You will start to see it coming live over the next 7 days. As usual, Android will be first ( probably already is live ), with iOS and OSX being last. If you have a Windows or OSX version directly from this site, or through GoG, you should see an UPDATE menu option appear on the main menu. GoG.com will also go live with the update in their time.
There are a embarrassingly large number of bug fixes in this version. Thanks to a number of very eagle eyed players, in particular Mark Wright, I have been able to fix up many specific differences between the initial release version and the original 1985 release. I also spent a large amount of time pouring over the original code, looking for anything that might alter the way the game played in a way that I might not have foreseen.
On the whole, I think we have most of them, but there is always a chance that there are a few differences still. In particular, the remake is based on the original ZX Spectrum version, and there are definite differences between the Spectrum and the C64 version. So, if you were a C64 player, then the game will not being playing quite as you remember it.
The last few weeks has really made me understand the intricacies of the original game to a level that I never fully appreciated before. It’s quite amazing the small amount of time that the original game was developed and tested in, that said, it’s because of that that you understand why the original had more problems than Lords of Midnight ever did.
There are a number of bugs or oddities that I have chosen not to fix, these are because they are in the original. To players coming to the game anew, or even returning to the game without the same outlook of 30 years ago, some of the AI logic might not make a great deal of sense. I intend to address these issues in a later version by adding different playing modes.
The intention is to have the following playing modes, Original Spectrum, Intended Spectrum, Original C64, Updated.
Intended Spectrum will fix a couple of obvious bugs inherent in the original release, the main one being movement. There are some movement values that would change the way certain races move across particular terrain, for example giants and mountains, but these were never applied in the original due to a bug that referenced the wrong table.
The Original C64 will apply a couple of AI differences to the Spectrum version, namely the aforementioned movement issue. In C64 the functionality was added, but the terrains are different than the Spectrum Intended version. The other change would be that recruited lords start at dawn in the C64 version I believe. Please feel free to call out any other known differences ( apart from the sun 🙂 )
Updated will allow me to make a number of slight AI changes.
Firstly I will change the behaviour of fighting critters. I think it’s wrong that a lord with an army can be killed by a critter, especially on not much more than a flip of a coin. Currently a Lord’s army takes damage from the critter, which should remain, but a lord should not engage the critter until the army is wiped out.
Secondly, I will add some changes to make it less likely that a lord that you attack just continues on with their objectives and completely avoids a battle. I think that if they start the night in a location with an enemy army, there should be a large chance that they remain there and engage in battle. If they are near a location with an enemy army, there should also be a smaller chance that they will attack.
This week has seen The Lords of Midnight finally get the 1.12 update across all the stores. That means that OSX and Blackberry players can now enjoy the features that other users have had for nearly 4 months. Sorry about that, the OSX issue came about because I could no longer submit to the App Store, and it has taken this long for Marmalade to fix the issue, and Blackberry was just an oversight – never noticed that I had not updated it.
Doomdark’s Revenge has now hit version 1.2 across all stores. This resolves a number of early issues and brings the remake more inline with the original. There is still some work to do on that, and version 1.3 should be pushed out later this week which will hopefully close off the remaining problematic areas. You can see a full list of upcoming changes here.
I’ll be honest, it has taken me by surprise at the number of issues that crept through the testing process. Looking at it with hindsight, not enough testing occurred that compared it to the original. I have spent a large amount of the last two weeks pouring over the original code looking for subtle things that I had previously missed, in order to try and explain the variances. For example, Shareth’s stronghold is Imiriel, but for the routing AI it get overridden as Glireon. Morkin is actually and AI lord which means he moves. And, Characters will not attempt to recruit another character while at a stronghold.
The OSX version of Midnight and Revenge both have a problem with Mac Book Pro Retina screens. I shall be looking into that. As a work around, place you laptop in one of the smaller virtual resolutions, start the app and then change it to Large Window mode in the options. The change you desktop resolution back.
I’ve been working my way through the outstanding bug list. One of the areas that seems to cause contention, is battles.
It causes me some problems because the original is actually pretty haphazard where battles are concerned. So I’m going to talk about the battles in a little more depth, just so that you can get an understanding as to why certain things seem to be happening.
Firstly, night processing goes like this…
1. Reset all characters at dawn
2. Give all AI characters their turn
3. Process Battles
4. Place things on map
5. Move Mists
6. Remove things from map at location’s where characters are
7. Check if characters can recruit soldiers from strongholds
8. Re-spawn armies at strongholds
9. Check for important deaths
Secondly, the interesting point here is, characters are given a chance to move BEFORE battles take place. So, if you attack a character, there is a good chance he will move and thus a battle will not take place.
To understand that a little more, let’s look at the AI turn.
The AI character must decide what to do every night. Each character will react to a number of objectives.
1. Goto Liege
2. Goto Foe
3. Goto Object
4. Goto Home
5. Do nothing
If they have a liege, and that liege’s objectives are 1 or 2, then this characters objective also become 1 or 2.
Otherwise, we pick a new objective
When picking a new objective we pick a random number between 1 and 16. If we choose 1 to 5, then these are our objective. Otherwise we continue with our current objective.
So as you can see, there is a 68% chance that we will just continue on with what were we previously doing. Which means that unless you are at a characters stronghold, and his current objective is to go home, then the likelihood, he is moving away from you.
There is only a 6% chance that the character will stay at his current location.
Personally, I am very surprised at these stats, because it makes battles bloody difficult. Unlike The Lords of Midnight where a nearby army would drop everything to attack, or an attacked army would stay until the death, in Doomdark’s Revenge, everything apart from battle seems to be of more interest.
I have been looking into a couple of issues still plaguing Doomdark’s Revenge game play.
The first one is movement. I have to admit, I dropped the ball on this one. I wrote this code so long ago, that I assumed it was working. Well it isn’t. And there are three issues at play.
The first issue is actually a bug fix.
There are two versions of movement tables, one that the Spectrum used, and one that the c64 used. What these tables do, is decide which terrain the character gets for free. The problem is, the spectrum version had a bug. It didn’t point to the required table, it pointed to random memory. Therefore movement on the Spectrum doesn’t work as intended. I had fixed this bug. Which means, movement on the new version isn’t the same as either the Spectrum version of the C64.
Secondly, The Lords of Midnight movement code is based on leaving the current location. Doomdark’s Revenge is actually based on the location you are moving into. I had this wrong.
And thirdly, if you move into a location with a critter, you take a penalty. However because of the difference in the way I implemented the critters on the map, ie: 0 = NONE, whereas 0xff is NONE in the original. My critter check was always triggering. Thus you always got a penalty.
The three items combined, make for pretty shoddy movement, when compared directly to the original.