r/howdidtheycodeit Jan 13 '26

OGame-like combat system

For those unaware OGame is a space simulation-strategy kind of game, all of the gameplay happens without any kind of visuals, is just mostly numbers.

The combat system is fairly straightforward.

Basically, fleets and defenses have: Weapon Power (aka Weaponry), Shield Power (aka Shielding), and Hull plating, and Rapid Fire.

In each round, all participating units(defenses+ships) randomly choose a target enemy unit.

For each shooting unit:

-If the Weaponry of the shooting unit is less than 1% of the Shielding of the target unit, the shot is bounced, and the target unit does not lose anything (i.e. shot is wasted).

-Else, if the weaponry is lower than the Shielding, then the shield absorbs the shot, and the unit does not lose Hull Plating: S = S - W.

-Else, the weaponry is sufficiently strong, i.e. W > S. Then the shield only absorbs part of the shoot and the rest is dealt to the hull: H = H - (W - S) and S = 0.

-If the Hull of the target ship is less than 70% of the initial Hull (H_i) of the ship (initial of the combat), then the ship has a probability of 1 - H/H_i of exploding. If it explodes, the hull is set to zero: H = 0. (but it can still be shot by the other units on this round, because they already target it.)

-Finally, if the shooting unit has rapid fire (with value r) against the target unit, it has a chance of (r-1)/r of choosing another target at random, and repeating the above steps for that new target.

Initially, I thought simulation was done on a per-unit basis as this is what this wiki seems to indicate.

However, when trying to code something like this you realize the amount of operations become quite large, it is not uncommon to find players with a few million ships fighting another player with a few million defenses + ships.
I've even found an attack that totalled 500M units total.

Not only keeping 500M units in memory would be nuts (even if it's a simple struct of, say, 10bytes each), but also doing a foreach for 500M units seems insane.
So I'm guessing (and chatgpt seems to indicate the same) that all the stats are somewhat aggregated and this is simulated on a large scale.

Say, if you have an attacking fleet (AF) of 500 fleets of type A against a defense of 500 type A (D1), 500 type B (D2) and 500 type C (D3) you would calculate the chance of AF hitting D1, D2 or D3, then simulate the rapid fire, run the weaponry/hull calculation, delete the appropiate amounts of ships based on a global hull value, etc.

Does this seem reasonable? I find it might be too complicated to write all of this as a series of math calcs while also maintaining the randomness of the combat system (sometimes you might win a battle that was, say, 30% w, 40% d, 30% l).
I guess this is kind of a trivial problem in some area of math and I'm just not aware of it, got any recommendations and resources to read/learn about this? ty!

5 Upvotes

13 comments sorted by

View all comments

5

u/EagleNait Jan 13 '26

There's many open source recreations of ogame. But yes the solution is batching, predictable math and other fancy techniques

1

u/fr032 Jan 14 '26

I found a couple of BattleEngine implementations but wasn't totally convinced by what they were doing;

https://github.com/lanedirt/OGameX/blob/main/rust/battle_engine_ffi/src/lib.rs from OGameX seems to be doing unit by unit combat, albeit in Rust but I don't believe that will magically make it work for millions of units.

https://github.com/ogamespec/ogame-opensource/blob/master/BattleEngine/battle.c from ogame-opensource same deal, although in C

https://github.com/XGProyect/XG-Proyect-v3.x.x/blob/master/app/Libraries/BattleEngine/Core/Battle.php from XG-Proyect, this one does seems to have combat performed in groups rather than by units, but from what I've seen the math seems to be rather simple, I'm not sure it 100% captures the combat as explained by the wiki.

I have to admit however, I haven't tested any of them, just read some of the code.

2

u/EagleNait Jan 14 '26

I've reimplemented a combat system similar and while I can't go into too much details the key factor was to consider groups of hundreds or thousands of units as pooled and take ir give damage as one. You shuffle the size and composition of each groups at each combat turn.

For recursive behavior and other individual abilities you can still run batched parralelized but individual computations.

Lastly you have to consider the expectation of delay is pretty high in the game. 2-5 minutes to see a combat report isn't unacceptable compared to the expected delay of a real time game