I would give each unit an amount of "credit" every turn, adding to the "account balance" (let's call it "readiness") from the last turn. Every realized attack subtracts a debt. This works with simple integers too, no need for floating point or complicated math.
For that, you would need an array of readiness values (or rather, pairs of readiness and unit ID, to be practical). Initially the array contains only zero values. Every round, for every unit, you add the unit's speed to its array entry. Slower units add a bit less, faster units add a bit more.
Next, sort the array, then iterate over the array. For every array cell, check whether the readiness value is above some chosen threshold. If that's the case, the unit (assuming it's still alive) makes one attack and the threshold value is subtracted from the readiness value. Continue from the beginning until no more unit can be found that is above the threshold. Since the array is sorted, you can optimize this to abort iterating as soon as the first unit is found that is not above threshold (all following ones are consequently not above threshold either).
End of round. Remove dead units.
That way, you have some very flexible properties:
- slightly faster units attack within the same round, but before slower units (possibly killing them before they can attack)
- more-than-slightly faster units will attack once per round, and will occasionally get a second attack at the end of the round (but before anyone else next round!)
- even faster units will get two attacks every round (one at the beginning and one at the end) and maybe a third attack every few rounds
Normal units: 100
Speed units: 125
Super speed units: 150
Killer speed units: 220
Slow spell: subtracts 20
Freeze spell: subtracts 100
Units A and B are normal units. They start with zero readiness, adding 100 every round, which is above (equal to) threshold. Thus, every unit strikes once every round. Every attack costs 100, thus leaving the unit with 0 readiness after the attack.
Now B uses a speed potion. A still adds 100 to readiness, but B adds 125 every round (doing one attack and taking the excess 25 along to the next round):
round 1: A=100 B=125 --> B strikes first
round 2: A=100 B=150 --> B strikes first
round 2: A=100 B=175 --> B strikes first
round 3: A=100 B=200 --> B strikes first, then A, then B again
A realizes that B is speeded, and uses a killer speed spell. It now adds 220 to its readiness every round (i.e. 2 attacks per round, and taking along 20 to the next round, accumulating to a 3rd attack in 5 rounds):
round 4: A=220 B=125 --> A strikes first, and strikes again
round 5: A=240 B=150 --> A strikes first, and strikes again
B casts a freeze spell at A, which also hits C who is inside the AoE. A now adds 220-100 = 120 to readiness every round, whereas C adds 0:
round 6: A=120 B=175 C=0 --> B strikes first, then A, C is frozen
round 7: A=140 B=200 C=0 --> B strikes first, then A, then B again, C is frozen
round 8: A=160 B=150 C=0 --> A strikes first, then B, C is frozen
round 9: A=180 B=150 C=0 --> A strikes first, then B, C is frozen
round 10: A=200 B=150 C=0 --> A strikes first, then B, then A again, C is frozen
If C was a "speedy" unit, it would still be allowed to strike once every 4 rounds.
Edited by samoth, 04 September 2013 - 05:24 AM.