Skip to content

Instantly share code, notes, and snippets.

@ekimekim
Created June 11, 2013 17:55
Show Gist options
  • Save ekimekim/5759139 to your computer and use it in GitHub Desktop.
Save ekimekim/5759139 to your computer and use it in GitHub Desktop.
An arbitrary-complexity calculator for neptune's pride battles, including documenting losses of fleets. Currently only has a python interface, and it's horrible. Also included, code for a simple two-way-only calculator.
def combat(*forces):
"""Run a combat between any combination of forces.
Each force represents all involved ships owned by a given player.
The first force should be the defender, with forces then proceeding in order of player index (wrapping around).
Each force has form (player_WS, force_list).
Each force list should be a list of integers, giving the ships of the player and how they're split.
The force list should be the order in which the ships fight.
Note that, in a normal situation, a player's ships orbiting a star fight first,
followed by each fleet they have, from largest to smallest.
Each force list will be modified in-place to account for losses.
Thus, only one force list will remain non-empty upon return.
This force list will contain one or more remaining groups of ships, though possibly less than it started with.
This reflects lost fleets.
As an extended example, consider a fight between 3 players.
Let's call them player 1, 2 and 3, with 2 defending.
Player 1 is attacking with 200 ships in one fleet, and 2 WS.
Player 2 has 100 ships on their star, with two additional fleets of 50 and 75 ships, and 1 WS.
Player 3 is attacking with 150 ships in one fleet, and 50 in another, and 2 WS.
Then we would call this function thus:
p1 = [200]
p2 = [100, 75, 50]
p3 = [150, 50]
combat((2, p2), (1, p3), (2, p1))
And a possible result might be:
p1 == []
p2 == [25]
p3 == []
ie. The defender won, but lost one of its two fleets.
"""
# TODO this entire thing is horrible
# add 1 to first force's WS
forces = [(ws + 1 if n == 0 else ws, force_list) for n, (ws, force_list) in enumerate(forces)]
# this is the only way to loop when we need to be able to remove things during the loop
i = 0
next = lambda x: (x+1) % len(forces)
while 1:
damage, force = forces[i]
while damage:
_, target_force = forces[next(i)]
dealt = min(damage, target_force[0])
target_force[0] -= dealt
damage -= dealt
if target_force[0] == 0:
target_force.pop(0)
if not target_force:
forces.pop(next(i))
if len(forces) == 1:
return
i = next(i)
def simple((def_WS, def_n), (att_WS, att_n)):
"""A simplified interface for a simpler situation:
This is for two-player fights between single collections of ships,
or if you don't care about whether fleets survive.
It returns (def_won, remaining) where def_won is true if defender won, else false,
and remaining is the number of remaining ships on the winning side.
"""
att_left = att_n - math.ceil(def_n/att_WS) * (def_WS + 1)
def_left = def_n - (math.ceil(att_n/(def_WS+1)) - 1) * att_WS
if def_left > 0:
return True, def_left
else:
return False, att_left
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment