Temple of The Roguelike Forums

Development => Programming => Topic started by: loom_weaver on June 16, 2011, 05:26:41 AM

Title: Slow Attack/Movement Speed
Post by: loom_weaver on June 16, 2011, 05:26:41 AM
In several roguelike's it's common for some monsters to move more than one tile per turn or attack several times a turn.  Quicklings, dual wielding, etc. are all plausible reasons.

What are your thoughts on monsters that attack or move less than 1.0 per turn?  For example a giant wielding a great maul who swings once every two turns.  Or a heavily encumbered creature that can only move the equivalent of 2 tiles every 5 turns.

I have a system in my mind based on action point accumulation that could implement this but I'm beginning to doubt that these slower than 1.0 cases are even a good idea.  The reason is because it's not obvious at any given turn if the monster is going to move/attack or just sit there.  Likewise if your player is slowed then you'll be skipping turns (although this latter case could be avoided by scaling time to player always moves at least 1.0 / turn).  Anyways your thoughts?
Title: Re: Slow Attack/Movement Speed
Post by: NON on June 16, 2011, 06:20:05 AM
Shouldn't there be any creatures the player can run away from?
Title: Re: Slow Attack/Movement Speed
Post by: purestrain on June 16, 2011, 06:43:32 AM
Well; if there is a monster that moves faster, why shouldn't there a monster which moves slower? If you can transform into the faster one, then its obvious that others can act only evey two or three turns (in the players point-of-view).

But maybe you can tell my why there is some point-accumulation system necessary? Doesn't an action just take n seconds of time and after n seconds its your turn, regardless of how many other actions occured within that timespan? I can't remember any game where i have actively skip turns because i'm slowed down.
Title: Re: Slow Attack/Movement Speed
Post by: Darren Grey on June 16, 2011, 08:41:06 AM
I assume the action point stuff will only go on in the background, so your turn won't come round until your action points have been replenished.  Other games do this too.

ADOM has monsters called molochs which move at around half speed, have immense armour, and hit like a tonne of bricks.  They're one of the more memorable monsters to encounter because they require some unique strategies (like playing hack n back without taking any hits if you time it right).

In general it's good for the player to have a way to run away from enemies, so making most of them have 90% speed ain't a bad idea.  They'll still attack most rounds, but if you want to leg it then you should be able to, given the space.
Title: Re: Slow Attack/Movement Speed
Post by: Z on June 16, 2011, 06:39:26 PM
Lots of roguelikes have slow monsters (which probably are much stronger as a compensate). However, even after such compensation, these monster are often no challenge. If you move 2 times faster, you alternate between attacking and escaping. If you move 1.5 times faster, you move twice and attack once. With more complicated speed ratios the good hit-and-run method is more complicated.

This may be interesting for newbie roguelikers, but IMO this becomes boring once you get used to it. Care should be taken that such mechanical hack-and-back is avoided. Make slow monsters ambush you from several sides, use missiles, have them accompanied by fast monsters, or whatever.

A monster which moves at the same speed but hits more rarely does not have such a problem.
Title: Re: Slow Attack/Movement Speed
Post by: purestrain on June 16, 2011, 07:14:59 PM
I would suggest that movement commands are executed after a postduration so they could be aborted. This way a slow monster could counter attack if the player moves adjacent to them. I'm mostly using actions which can be aborted by environmental conditions.

E.g. if you choose an attack which is really hard it takes time and can be interrupted by fast attacks.

Any drawbacks which i'm not seeing here?
Title: Re: Slow Attack/Movement Speed
Post by: Xecutor on June 17, 2011, 01:14:20 PM
When slow and hard-hitting monster is accompanied by fast yet fragile minion that
can slow/paralize/catch the prey, it can be much more fun :)

In addition to natively slow/fast monsters there are almost always such things as haste and slow effects.
So, unless you don't have any speeds at all, it is always a factor to consider.
Title: Re: Slow Attack/Movement Speed
Post by: loom_weaver on June 22, 2011, 01:55:26 AM
This may be interesting for newbie roguelikers, but IMO this becomes boring once you get used to it. Care should be taken that such mechanical hack-and-back is avoided.

To avoid this scenario I'm designing my game to have movement and attacks on two separate activity point accumulators.  Then each turn the intention is that you move first and then do your activity e.g. attack.  Once you do a non-movement action, you can no longer move during your turn.

The accumulators work like this:
weapon attacks cost 100 points (attack speed points) for each attack per turn
movement costs 100 points (movement points) to move one tile per turn

Every mobile gains a set amount of attack speed points and movement points (amt) per turn.  100 is average, 150 is 1.5x average, and so on.

At the beginning of each turn, your points are calculated as
Code: [Select]
points = (points % 100) + amt
For example, let's say you have 80 attack speed points and you gain 110 per turn.
In the current turn you cannot attack as you need at least 100 points.
Next turn you have (80 % 100) + 110 = 190 points.  You attack once leaving you with 90 points.
Next turn you have (90 % 100) + 110 = 200 points.  You can now attack twice this turn leaving you with 0 points.
Next turn you have (0 % 100) + 110 = 110 points.  You could attack once but decide to wait.
Next turn you have (110 % 100) + 110 = 120 points.  You still can only attack once.

On average you get 1.1 attacks per turn and the equation means "use it or lose it".

Title: Re: Slow Attack/Movement Speed
Post by: Yobgod on June 24, 2011, 01:50:37 AM
Oddly, I was thinking about movement/time systems on my drive home today and am working on the skeleton of a blog post.

My problems with activity point accumulators are:
1) You may need an accumulator per-creature, per-activity capability (locomotion, manipulation, sensing) which can quickly add up given sufficient NPCs.
2) They can often interact oddly with 'rest' actions, or else require complicated algorithms to determine how much surplus activity can be stored before use.

My solution is based on probabilistic tick-scheduling.

Basically, you use whatever appropriate speed applies to an action (may be calculated on a case by case basis) to schedule on which future tick the even will occur, but you keep any fractional tick stored with the event. So, for an action of length "2", a character of speed '1.0' would schedule it for NOW+2 and record "0" as the fractional tick of that activity. Another character of speed "0.9" would also schedule for NOW+2, but would record "0.22" as the fractional tick.
[Note that you can choose to scale speeds so that the player is always speed '1.00' for convenient turn-based play.]

An initial approach might just sort based on the fractional time and execute actions sequentially. I don't like that because it makes an activity of length 2.0 always take twice as long as an activity of length 1.9, while 1.9 and 1.1 occur with the same frequency. This becomes especially noticeable during chase scenes and leads to an artificial importance on doing whatever is needed to 'crack the next numerical boundary'.

A better approach will roll a random probability for each activity with non-zero fractional tick. If the probability is greater than the fractional tick, the activity happens, otherwise it is rescheduled (with 0 fractional tick) for the next round. This can fairly simulate sub-tick speeds within a tick-based framework, and works pretty well.

But wait... this can still lead to statistical weirdness when slower critters get lucky while faster ones get unlucky. Fairness is only guaranteed over a long interval, and unfairness over even a short interval can lead to perceptions of wrongness or untimely death. Fortunately, there's an even better tweak that, coincidently, makes things simpler.

Every tick, generate a -single- probability roll that is compared against every fractional action potentially occurring that tick. This both saves wear and tear on your RNG and guarantees that a faster critter never ends up acting slower than a slower critter. They may go neck and neck for a while, but the faster critter will eventually break away/catch up.

Another nice benefit of this technique is that is allows arbitrary precision in your speeds without requiring arbitrary precision in your ticks... you just need the single probability per tick to be generated with sufficient precision to discriminate between the speeds.
Title: Re: Slow Attack/Movement Speed
Post by: Ari Rahikkala on June 28, 2011, 04:48:01 PM
At the beginning of each turn, your points are calculated as
Code: [Select]
points = (points % 100) + amt

Are you sure you mean this, rather than points = min (100, points) + amt (or some other more reasonable surplus limiter)? With the modulo, wouldn't it be really difficult to predict how many attacks you're going to get on the first turn of a fight? (unless the numbers are actually visible, in which case you might be waiting a while to optimise your attack points - pity the guy with 101 speed, especially if he overshoots tho wait and loses his 200 attack points before using them)
Title: Re: Slow Attack/Movement Speed
Post by: loom_weaver on June 28, 2011, 05:15:34 PM
At the beginning of each turn, your points are calculated as
Code: [Select]
points = (points % 100) + amt

Are you sure you mean this, rather than points = min (100, points) + amt (or some other more reasonable surplus limiter)? With the modulo, wouldn't it be really difficult to predict how many attacks you're going to get on the first turn of a fight? (unless the numbers are actually visible, in which case you might be waiting a while to optimise your attack points - pity the guy with 101 speed, especially if he overshoots tho wait and loses his 200 attack points before using them)

Correct, the whole point of using the modulo is to prevent players from trying to 'stock-up' or 'hoard' points before the first attack.  The values would be hidden from the user although there probably would be some kind of indication if they cannot attack that turn.

The problem of using min(100, points) + amt is that it breaks for creatures with < 100 attack speed e.g. a slug with amt = 50 would be able to attack every turn when it is intended to only attack once every two turns.

The person with 101 speed i.e. amt = 101 will always be able to attack at least once at the beginning of each turn.  I see your point though... if he tried to hoard his unused points it would be a long wait to get that second attack and if he didn't use it then it's gone for another 100 turns.  However, I don't think that's a big concern because I'm trying to discourage this style of play.

This system could be augmented so that if you are out of combat your current points (once they hit 100) will remain at max(100, amt).  This will add some more certainty to the start of a fight but I'll have to think about it a bit more.
Title: Re: Slow Attack/Movement Speed
Post by: loom_weaver on June 28, 2011, 05:32:24 PM
Oddly, I was thinking about movement/time systems on my drive home today and am working on the skeleton of a blog post.

My problems with activity point accumulators are:
1) You may need an accumulator per-creature, per-activity capability (locomotion, manipulation, sensing) which can quickly add up given sufficient NPCs.
2) They can often interact oddly with 'rest' actions, or else require complicated algorithms to determine how much surplus activity can be stored before use.

My solution is based on probabilistic tick-scheduling.

1. Primarily this is for movement rate and number of attacks per turn.  I haven't thought about other actions but I was assuming that casting spells, etc. would always be 1 action / turn.
2. I see your point here.  If I don't store surplus activity or reset the accumulator then slow monsters will end up attacking once every round and fast monsters would be attacking slower than people think they should.  Overall if I could avoid surplus activity storage completely I would.

Can you provide a few more examples with probabilistic tick-scheduling?  Overall my goal is to allow fast monsters to attack > 1 per turn, slow monsters < 1 per turn (both at non-discrete amounts), and avoid unfairness around wait states and combat openings.

My system with the modulo is still in the design stage and it's the best I could come up with so far.  I'm definitely interested in spotting flaws in it and learning about better systems.
Title: Re: Slow Attack/Movement Speed
Post by: Z on June 28, 2011, 06:55:01 PM
Loom_weaver's method means that a being with speed e.g. 3.2 gets either 3 or 4 moves per turn, and it gets the fourth move once per 5 turns. Two low significant digits are used to determine when the extra move is given, and the other digits count the number of moves left in the given turn. Operation "% 100" means that a being can just do nothing and lose a turn.

Quote
The problem of using min(100, points) + amt is that it breaks for creatures with < 100 attack speed e.g. a slug with amt = 50 would be able to attack every turn when it is intended to only attack once every two turns.

That's not true. It moves each second turn as it should. Or I don't understand the system correctly. Also it does not really allow to "hoard" moves, only one move (which could be hoarded anyway by a smart player who understands the speed system well). So it just lets the being with speed 101 to use this second attack in the moment they want to (as long as it was at least 100 turns after the last second attack, or they skipped some move in the meantime), not when the system decides.

But there is one thing I don't like about your method. Suppose you have two monsters A and B with 150 speed, and they both start with 0 points. They will move in the following pattern: A-A-B-B-A-B-A-A-B-B-A-B-A-A-B-B-A-B. From B's point of view, A will move either 0, 1, or 2 times between each two of B's moves. Since both are of the same speed, they should alternate, right? I have noticed a similar behavior when fleeing from monsters in ADOM and it was annoying. It's even worse if you have two monsters with speed 300. Why should they attack each other in pattern A-A-A-B-B-B? (ADOM solves this problem by setting the "move-each-turn" speed to be 1000 and making a normal speed 100 monster move once each 10 turns, but it still does not get rid of the previous artifact.)

But I recommend using a very simple and natural system I mentioned in this thread (http://www.roguetemple.com/forums/index.php?topic=138.0). It does not have such artifacts.

Another thing I don't like about sophisticated speed systems (monsters of different speeds performing actions of different complexity) is that it might become very hard to predict who will move next. This might be good or bad, probably a personal taste: one could claim that observing the movement pattern to achieve correct predictions is an interesting challenge, but I prefer something simpler. In Hydra Slayer speed is always a power of two, which makes the scheduling easily predictable.
Title: Re: Slow Attack/Movement Speed
Post by: loom_weaver on June 28, 2011, 09:21:25 PM
Quote
The problem of using min(100, points) + amt is that it breaks for creatures with < 100 attack speed e.g. a slug with amt = 50 would be able to attack every turn when it is intended to only attack once every two turns.

That's not true. It moves each second turn as it should.

Whoops, my bad!  I was thinking max(100, points)...


But there is one thing I don't like about your method. Suppose you have two monsters A and B with 150 speed, and they both start with 0 points. They will move in the following pattern: A-A-B-B-A-B-A-A-B-B-A-B-A-A-B-B-A-B. From B's point of view, A will move either 0, 1, or 2 times between each two of B's moves. Since both are of the same speed, they should alternate, right?

I agree that interleaved is better especially when it comes to movement (I have a mud background and clumped attacks is natural).  However, isn't this a case of choose your own poison?  On one hand the turn order is very defined but you get clumping, while on the other hand you get nice interleaved attacks/movement but cannot predict who will move next.

Considering that my game is tactical turn-based I am initially leaning towards the former.  I don't see how your system can avoid both drawbacks but I could be missing something.
Title: Re: Slow Attack/Movement Speed
Post by: Z on June 28, 2011, 10:55:16 PM
I don't think your system solves the problem of unpredictability, as the occasional extra move is unpredictable, and these extra moves are important for beings of speed < 200. Also my system is actually more predictable when the two beings have exactly the same speed, since then they just alternate moves.

With three moves per turn you could e.g. have an archer who steps out from behind a corner, shoots, and hides back. (Not that it is a necessarily bad thing, it could be interesting.) Most roguelikes do not work this way, contrary to party-based tactical games such as Exile/Avernum or X-Com. I think that's because alternating moves are natural for roguelikes, but party game designers think that constantly changing characters is too cumbersome.
Title: Re: Slow Attack/Movement Speed
Post by: Yobgod on June 29, 2011, 02:57:43 AM
Quote
Can you provide a few more examples with probabilistic tick-scheduling?

I will say that there is a limitation in that your tick has to be the shortest possible action. With that in mind, let's set our system as 10 ticks per turn, with "normal" player actions taking 10 ticks each. Let's also define a speed 0.7 "Troll" and a speed 1.8 "Kobold". Time for a race!

Player: steps take 10.00 ticks. Schedule first step at tick 10/0
Kobold: steps take 5.56 ticks. Schedule first step at tick 5/56
Troll: steps take 14.29 ticks. Schedule first step at tick 14/29
The remainder indicates the percentage likelihood each action that the action is delayed one round.

tick 5: RNG 62 - Kobold steps and schedules for tick 10/56
tick 10: RNG 39 - Kobold reschedules to 11/0. Player steps and schedules for 20/0. Note that the Kobold had a 44% chance of going (again) before the player here.
tick 11: Kobold steps and schedules for 16/56
tick 14: RNG 67 - Troll steps and schedules to 28/29
tick 16: RNG 29 - Kobold reschedules for 17/0
tick 17: Kobold steps and schedules for 22/56
tick 20: Player steps and schedules for 30/0
tick 22: RNG 45 - Kobold reschedules to 23/0
tick 23: Kobold steps and schedules for 28/56
tick 28: RNG 28 - Kobold reschedules to 29/0. Troll steps and reschedules for 42/29

So, what we'll seen so far is: KPKTKPKTKP, which is pretty reasonable for the large disparity in movement rates we have.
Where this system really gets interesting is when creatures have similar speeds but one is slightly faster or slower.
I like it because it doesn't seem to have any strange artifacts like slower creatures occasionally going twice before a faster creature and because it isn't completely deterministic thanks to the RNG each tick, so you can't rely on or exploit, say, getting an extra move on every sixth attack.