Movement is now movement

Back in the V3 (first post), I announced there will be changes to how map works. In Map and vision, a month later, I demoed the first prototype of a new topography-driven Dominance map. Finally, today, we have the map taking affect on how the movement works and vision is calculated.

Obligatory history lesson

V1/2 had no map, we all know this. They had objects, objects had coordinates, and that’s about all that existed – relationships between objects were measured in distances, and if distances were smaller or larger than an arbitrary value, an action would occur. The load of calculating distances, that was done in the database itself, was enormous, and further arbitrary measures had to be taken, such as the Green circle (for the unlucky few that remember it), were used to limit the amount of calculations to some usable numbers. At the height of beta 5, vision calc alone took up to 15 minutes out of a 30 minute tick. With tons of optimizations that was drastically reduced during beta 5 3/4, again thanks to the fact Dominance had no map.

V3 does have a map. So far (during alpha) we have treated it as cosmetic addition to the background, but yesterday vision calc for the first time took topology into account:

How does it work? Using the same mechanism moving over terrain does – so there won’t be any surprises to players – a downward slope is free, an upward slope costs double. So, for an avatar  that’s positioned on a tile at height “2”, when looking downwards the vision range is increased by 1 for every downward slope, up to and including height level “-1” (water). On the image above we have a simple scenario where two height levels interweave, and the avatar has vision range of 6 and 7, depending on the side he’s looking at.

How much does this cost us? Significantly but not debilitating. Movement is much more costly, and we’ll have plenty of opportunity to optimize later.

Movement works by the exact same principle:

A caravan has a fixed speed of 2 (minimum required to climb uphill). In the first tick it climbs on the slopes of Mt. Shallow. On the second tick it reaches the top, but although its movement “speed” is only 2 and it has spent it all climbing, the downward slope is completely free – so the caravan plunges down the … shallow slopes of Mt. Shallow and ends movement at the bottom.

If a caravan or avatar doesn’t have the moves to climb, it will end movement altogether. This only happens when remaining moves are at 1, as the slope requires 2 moves to climb.

How much does this cost us? An arm and a leg. See interception below.

What about obstacle evasion?

What about it? We have no obstacles, we have cost deltas. If for example, hills were 2 moves, high mountain 3 moves etc, then it would make sense to move around the hills, but we do not deal in absolute costs, but relative ones. Movement at the same height costs the same whether we’re in valleys or on mountain peaks. Whatever moves you lose climbing over a mountain, you’ll regain in free moves when descending. This method does not put players that spawn atop high peaks at any significant advantage or disadvantage, and takes into account that, realistically speaking, mountain ranges are huge and avatars are small. Mt. Shallow in the example above, is only 25km wide. It’s no more than a hill.

Avatar interception

Now that we have avatars that move, finally they don’t have to teleport around. In the last alpha (oh, by the way, we had an alpha yesterday!) Entity.(Dracos) made a fool out of me by jumping his unladen European avatar from one of my villages to another of my villages over the head of my encumbered-with-Haadars avatar with speed 2 (his speed was 6), and I could not reach him. Now, if he tried the same thing, he’d actually move hex by hex and run head into my forces – battle would ensue – and the unladen avatar would be turkey.

So how does movement work? Imagine we had a slew of avatars, with “speed” ranging from 2 to say, 7. We run all the avatars and move each 1 hex, taking into account terrain costs – some would move 1 hex for free, others for 2 moves, but most would spend the regular 1 move. Then we run combats. Then we move them again for 1 hex, then combats. At this stage those avatars that only had 2 moves would stop and we continue moving those that had 3+. The pool of avatars we’re moving decreases by each iteration, so in the end we had 7 iterations of moves (or 15, if some avatar found that “perfect slope” and ran it downward for 7 hexes straight).

For avatars that move towards static targets – this is no issue. For attacking avatars that are gunning for monos, thrones or setts, again, no issue. But for those avatars that are chasing live targets, we have to recalculate movement path each step of the way. This costs.

Furthermore, we just ran 7 (or 15) checks for combat. THAT is expensive. And, to make matters worse, we’re still not done. It’s conceivable that an avatar hit an enemy on the 7th move, combat was resolved, avatar lost and retreated one free move towards their throne, and on that exact spot hit another enemy. So we need to run combats for the 8th time. And what if they lost again, retreated and hit another enemy? 9th time. In essence, we now run combat checks for as long as necessary until finally no one is fighting anyone else.

This just pumped our tick resolution to approx. 2 seconds, for a test case with some 8 elders. I expect that for a hundred or two players we may be looking at a dozen seconds per tick.

Not to worry, no optimizations have yet began – and the first one I intend to do is to load the map objects during tick from database to memory and run collisions from there.