To Luxor, everything now grew clear

Clumping together...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.

  1. Head Home
  2. Head Home
  3. Head Home
  4. Follow Luxor
  5. Head Home
  6. Follow Luxor
  7. Follow Luxor
  8. Follow Luxor
  9. Search for object
  10. Head home

Now Talormane does this

  1. Head Home
  2. Head Home
  3. Search for object
  4. Search for object
  5. Follow Lorelorn
  6. Follow Lorelorn
  7. Follow Lorelorn
  8. Follow Lorelorn
  9. Follow Lorelorn
  10. Follow Asorthane

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.

First week snagging…

20140220-084247.jpgRelease week is always frustrating. On Android I just cannot test on enough devices, so I know that something is always going to bite me, and Monday morning it did. None of my Android testers had had any problems with the game loading, but Monday morning a number of devices were reporting that the game wouldn’t load. Later that night I spent a few fraught hours fighting with hotel WiFi trying to get an update tested by the affected customers, and then released.

In this instance it was an easy fix. In fact, I had already addressed the issue the previous week for the Windows release. Some last minute testing on my Mac Desktop running a windows VM, full screen, highlighted an issue of loading the splash screen. At the high resolution the splash screen was larger than 2048. When this image was being loaded, it was converted into a power-of-two texture and thus a 4096×4096 texture. The texture loader I was using was choking on that. A quick change to the affected images, across all resolutions, resulted in a fix, and a 5mb reduction in app size to boot!

This was the problem that affected some Android devices. So all I needed to do was rebuild the current version for Android and send it back out. In the end, the Android release was probably a lot smoother than The Lords of Midnight.
Continue reading

Tunnel Vision

tunnel_statusI’ve been working away for the last few weeks, which has meant that my development has had to take into account that it is being done primarily in bars an restaurants. I know many of you are waiting for the latest version of The Lords of Midnight, but although I have spent some time fixing bugs and adding a few new features, I am not in a position to Build a release version. I have to have access to my desktop to do that, and the few days I’ve spent at home with my family, I hope you can understand that spending time in my study on my computer is not the highest order of the day.

After declaring an end to any changes to Lords of Midnight, I spent some time merging the codebases of the different versions that have been branched out over the the year. Namely, Mobile version, Desktop Version, and Doomdark’s Revenge. I now have a unified code base which means that when I release a update for LoM soon, it can be across all formats.

Once the merge was complete I decided to spend some time working on Doomdark’s Revenge. I am hoping to release a test version soon. The night AI will not be activated but you will be able to wander around the map, above and below ground. And generally check out the UI differences between the games etc. This will then give me a good base to slowly turn on AI features and test them thoroughly up to release later this year. For the record that would be in about 12 weeks!

Once area that I have been working on this week, is tunnels. Tunnels are one of the new features that Doomdark’s Revenge implemented. So I have been slowly working my way through the code base, adding in all the little things that need to be there in order for them to work.

It’s a little different with The Midnight Engine, ( which by the way is the underlying code that powers both The Lords of Midnight and Doomdark’s Revenge ), over the original games, in that there is one code base. Doomdark’s Revenge was released as completely new game, and therefore much of what didn’t remain of The Lords of Midnight was just removed and the new code was added. This is a big issue with my codebase, as my original brief for creating The Midnight Engine was to be able to play both games and in theory create a game that mixes the features from both LoM and DDR. So, if we take tunnels as an example, I could just turn tunnels on in LoM, and everything would just work.

Now, let me try and give you an example of why that thought process gives me a nightmare when implementing something like tunnels.

In LoM a map location is split up into [ Terrain, Area, Object, Flags ], in DDR it is just [ Terrain, Flags ] – both area and object are generated. TME uses an expanded format [ Terrain, Variant, Area, Climate, Flags, Object ]. So the generated areas in DDR are stored, as are the objects. ( For the record, objects change every night ). For both, objects are classed as things you find or things you see. So Guidance, Cup of Dreams, Dragons, etc…

Now tunnels are a flag. A location has a tunnel beneath it or it doesn’t. If the terrain is GATE, PIT, PALACE, CITY, then the tunnel is an entrance/exit. If the terrain is PLAINS, FOREST, HILLS, MOUNTAINS, then it is considered a passageway. Now, this is where things start to get messy.

A tunnel location can only have a critter ( dragon, wolf, skulkrin, trolls ), when it is a passageway. And the location directly above ground can only have a critter when there isn’t a passageway below. So affectively you have two locations sharing the same space but only one critter at the location who could be in either of the two locations.

It seems a pretty straight forward thing to think about, but when your code base works on the concept of a single location, suddenly everything changes.

When drawing the landscape, the frontend asks the backend for the information about a given location. It draws the terrain graphics and any critter imagery that is required. The backend has just told the front end that there is a critter at this location. However, now it has to consider if we are above or below ground, and the type of below ground we are on. Based on that information the frontend can decide if that critter is visible or not.

When at a given location the frontend asks the backend for all the lords that are at a given location. But now it has to consider if that lord is above or below ground. The list of these types of checks goes on and I’ve found myself having to work through the engine making sure that I am always using the correct context. More importantly I am trying to make sure that any logic is in the backend and not in the frontend. Therefore the backend now returns the information in the form of, here is the information at the location requested, this critter is above ground and this critter is below ground. It doesn’t matter that there can’t be a critter in both, that is a backend problem not a frontend one.

A similar thing happens with the discovery map. There are flags on a location to say that it has been seen, looked at, or visited. Seen is a distance thing. Two locations away may have been seen, and you know what terrain is there because you can see it on the landscaping view in front of you, but you might not know what it is called. Looked at is for locations directly in front. You know the terrain and the name. Finally, visited is exactly that, you have stood on that piece of ground. But, you might not have stood under that piece of ground. So now we have to introduce the concept of tunnel visited and tunnel looked at. How about, we have walked down a tunnel and got to the end, and we know the tunnel finishes, as opposed to not quite making it to the end, so we have looked at the tunnel location in front, but because we didn’t visit it, we don’t know if the location after that continues as a tunnel, or this is indeed the end of the tunnel.

That one bit flag in DDR ‘tunnel’ suddenly becomes so much more when you are trying to keep a flexible engine. That one bit flag also creates limitations. Two tunnels adjacent to each other must be connected. You can’t run a tunnel under a palace because a palace is always an exit/entrance. This is used to create a one way tunnel in the game.

I have considered removing the bit flag, and replacing it with the concept of layered maps. You would then have a map for all the terrain above ground and then a map for all the terrain below ground. Following that approach would me that the limitations could be removed and it would allow things like different critters above ground than below. Or types of tunnels. But for now, I’ll leave well alone!

Other things have crawled out of the subterranean landscape… For example, two characters at the same location are not actually at the same location when one is above ground and one is below ground. Thus, the newly added grouping functionality suddenly needs to take into account tunnels!