Drop? garrison? carrier loss question

ill try to test, its just very time consuming. and I need multiple accounts etc.

not before and after combat, a drop and a pickup from different carriers following their arrival orders.
carrier A drops all, drops happen first
carrier B picks up all,

I think all carrier transfers happen after combat, and after Industry manufactures new ships.

If it happened before combat, then that was a previous tick before combat.

OK, well that was definately not how it previously worked before allied combat, dropping all ships on arrival meant NO carrier losses at all.
and largest fleets always fought first, till all ships were expended they were then destroyed.
then the next largest fleet engaged etc etc.

I have always been a little hazy on how ship losses are distributed amongst attackers when two enemy fleets arrive at a star controlled and defended by a third player.

Player A and B (enemies) arrive simultaneously at star controlled by player C
according to the current description on codex, A and B become a team against C
C fires first.
who loses those ships?
A? B? both of them at the same time? the one who flew shortest distance? half each?
If its half what if the defenders weapons level is an odd number like 2+1?
A and B lose 1.5 ships?
or does the defender shoot A on the first firing round then B on his second?
what if there is no second?

Jay changed the code around 2015 March. Click and Read this thread. The codex is out of date.

New Rules for Combat for Ships in Formal Alliances

Jay’s explanation for the new combat algorithm is that combat is always two sided, defender vs attacker, even when three or more empires arrive for the melee. This is repeated until one empire owns the star.

I have not yet been lucky enough to be in a three way combat, so really IDK.
My gut instinct is that Jay probably wanted to keep it simple, so what worked for two empires is expanded to three empires. Damage could be spread proportionally from smallest carrier or garrison to largest carrier or garrison.

Are you using a Mac ? not a Windows ? I ask because I had to manually insert carriage returns when I quote you. strange ?

That part of the codex is not precise, and is an issue concerning unclaimed stars, which is unrelated to combat.

When a star is unclaimed, WG are not operative, so carriers fly towards it 1/3 LY per tick.
When two empires arrive the unclaimed star at the same tick, the carrier which flew the shortest distance, which is the same as saying the carrier which arrived the earlier fraction of a tick, becomes the owner of the star, who then becomes the defender in the ensuing combat.

yeah I understood that, but couldnt think of another fair way to determine who a defender would choose to attack first if two enemies present themselves at the same time.
or who would gain the star if after grouped combat with the defender enemy fleets had the same fleet strength

yeah it just doesnt make it very easy to understand whats going to happen, especially when ship counts are very low,
for instance
A arrives with weap2 and 11 ships`
B arrives with weap2 and 11 ships
C has weap1+1 defender and 14 ships

I can put 22 vs 14 in the calculator, but thats not going to tell me who will have what when A+B face off for round 2. or who will be defender, and one ship can make the difference.

if damage is incurred evenly as a team, A and B will end up with 4 ships each. who then assumes the star for the second combat?
if A is fired upon first, then B in the second firing round the outcome could be totally different.

It being unable to predict what will happen and having no calculator changes the strategy immensely.
even the most mathematically savvy player who uses the calc extensively, factors in production rates and times travelled has absolutely no way of knowing how a battle will turn out.

if im faced with the 3 options of arriving before, at the same time or after, which is best?
is it better to knock out the defender C in collaboration with my enemy, splitting the losses?
only if i can understand who will have the larger fleet and assume the star for defence

or arrive before and battle defender C alone at 1+1, and face B with the certainty of 2+1 defenders advantage,

or arrive after B and C have sustained casualties and try against B as an attacker.

That is an interesting infrequent corner case question with a big impact, that only @JayKyburz can answer.

Either A or B will defend the star in the second round of combat with 4 ships each.
Does it make any difference whether carrier A or B arrived in a shorter distance ?
Does defender C attack carrier A first or carrier B first ?

Apologies if I missed stuff, I’ve not read the entire thread.

There is no ‘second combat’ - if I understand what you are saying correctly. Only one battle can be fought at a single star per turn.

If multiple players arrive at the same time then it shoves everyone into the same battle, whenever all the remaining players are allies then one of them takes ownership.

I have no idea what happens if some of the attackers are allies with some of the other attackers. Lets say we have attackers ABC and defender D. If A is ally with B, and B is ally with C but A and C are enemies.

My best guess is damage will keep being applied until all players are allies of each other.

noone is allied in this situation. its 3 enemies meeting on a star. at the same time.
we know A nd B will engage in combat as a team against Defender C until he dies, then one of them will assume the star and a second combat is fought between Aand B we just dont know how the damage from C is dealt to the initial attackers.
evenly? sequentially?

The player who was nearest the star will take ownership. Then battle is fought with that player getting the defence bonus. Damage is applied to each attacker then the defender.

  1. First attacker takes damage
  2. Second attacker takes damage
  3. Defender takes damage
  4. ^Repeat

When only one player is left that player takes control of the star.

I think there’s a small bug currently where both attackers will share Weapon tech level. It’s best not to think of fleets doing damage but instead of fleets taking damage each round.

(at least this is how it used to work)

def combat(universe, star):
    fleets = star.fleets_in_orbit

    # if the star is not owned, give the star bonus to the fleet who was
    # closest to the star before moving.
    # we can now assume that the star is owned by _somebody_
    if not star.player:
        closest_fleet = fleets[0]
        for f in fleets:
            if f.last_jump_dist < closest_fleet.last_jump_dist:
                closest_fleet = f
        star.player = closest_fleet.player

    # begin a report that tells the state of the star before the battle
    recipients = [star.player.user_id]
    for fleet in fleets:
        if fleet.player.user_id not in recipients:
            recipients.append(fleet.player.user_id)

    star_report = {}
    star_report["name"] = star.name
    star_report["uid"] = star.uid
    star_report["ss"] = star.strength
    star_report["es"] = 0  # end strength will be filled in after the battle
    star_report["puid"] = star.player.uid
    star_report["w"] = star.player.weapons.value

    # Sort all ships into teams.
    # Defenders are all ships allied with the owner of the star.
    # Attackers are all ships not allies with the star owner.
    attackers = []
    defenders = [star]
    attacker_total_strength = 0
    defender_total_strength = star.strength
    for fleet in fleets:
        if fleet.player.is_at_war(star.player):
            attackers.append(fleet)
            attacker_total_strength += fleet.strength
        else:
            defenders.append(fleet)
            defender_total_strength += fleet.strength

    if not len(attackers):
        # everybody is friends here so there is no need for combat
        return

    universe.log_hostility(star.player, attackers[0].player)

    # Calculate the defenders WS which is the best of all defenders +1
    # Calculate the attackers WS which is the best of all attackers.
    attacker_weapons = attackers[0].player.weapons.value
    for attacker in attackers:
        if attacker.player.weapons.value > attacker_weapons:
            attacker_weapons = attacker.player.weapons.value

    defender_weapons = star.player.weapons.value
    for defender in defenders:
        if defender.player.weapons.value > defender_weapons:
            defender_weapons = defender.player.weapons.value

    # defenders get home star ws advantage.
    defender_weapons += 1

    # begin a report that tells the state of each fleet before the battle
    attacker_report = {}
    defender_report = {}
    def report_fleet(fleet):
        report = {}
        report["n"] = fleet.name
        report["ss"] = fleet.strength
        report["es"] = 0
        report["puid"] = fleet.player.uid
        report["w"] = fleet.player.weapons.value
        return report

    for attacker in attackers:
        attacker_report[attacker.uid] = report_fleet(attacker)
    for defender in defenders:
        if isinstance(defender, Fleet):
            defender_report[defender.uid] = report_fleet(defender)

    # work out who won and which team won and what how many ships in the
    # winner should lose in damage.
    attacker_rounds_survived = math.ceil(attacker_total_strength / defender_weapons)
    defender_rounds_survived = math.ceil(defender_total_strength / attacker_weapons)

    attackers_win = False
    if defender_rounds_survived >= attacker_rounds_survived:
        winners = defenders
        winner_total_strength = defender_total_strength
        losers = attackers
        damage = (attacker_rounds_survived - 1) * attacker_weapons
    else:
        attackers_win = True
        winners = attackers
        winner_total_strength = attacker_total_strength
        losers = defenders
        damage = (defender_rounds_survived ) * defender_weapons

    # kill all the losers
    for loser in losers:
        loser.strength = 0

    # sort the winners by strength
    winners = sorted(winners, key=lambda f: (f.strength))

    # iterate though the winning carriers distributing damage fairly
    damage_to_distribute = int(damage)
    for winner in winners:
        if not damage_to_distribute or winner.strength < 1: continue
        winners_damage = int(math.floor(damage / (winner_total_strength / winner.strength)))

        # if this winners damage is more that what is left to be distributed,
        # reduce it.
        if damage_to_distribute < winners_damage:
            winners_damage = damage_to_distribute

        if winner.strength < winners_damage:
            damage_to_distribute -= winners.strength
            winner.strength = 0
        else:
            winner.strength -= winners_damage
            damage_to_distribute -= winners_damage

    # handle the case where rounding meant that not all damage was dealt
    while damage_to_distribute > 0:
        for winner in winners:
            if damage_to_distribute <= 0:
                break
            if winner.strength > 0:
                # don't allow any strength to go lower than 0
                winner.strength -= 1
            damage_to_distribute -= 1

    # give the star to the winning player with the most ships remaining.
    total_player_strengths = {}
    for winner in winners:
        if winner.player not in total_player_strengths:
            total_player_strengths[winner.player] = winner.strength
        else:
            total_player_strengths[winner.player] += winner.strength

    largest_player = None
    largest_strength = 0
    for player, strength in total_player_strengths.iteritems():
        if not largest_player:
            largest_player = player
            largest_strength = strength
        if strength > largest_strength:
            largest_player = player
            largest_strength = strength

    loot = 0
    if attackers_win:
        star.player = largest_player
        loot = star.economy * 10
        largest_player.cash += loot
        star.economy = 0
        star.calc_resources()

    # the final strength of the star.
    star_report["es"] = star.strength

    # the final strengths of the fleets.
    for attacker in attackers:
        attacker_report[attacker.uid]["es"] = attacker.strength
    for defender in defenders:
        if isinstance(defender, Fleet):
            defender_report[defender.uid]["es"] = defender.strength

    # The combat report
    data = {"template": "combat_mk_ii",
            "star": star_report,
            "attackers": attacker_report,
            "defenders": defender_report,
            "dw": defender_weapons,
            "aw": attacker_weapons,
            "loot": loot,
            "looter": star.player.uid,
            }

    universe.create_event(recipients, data)

    return True

this is the relevant bit

# sort the winners by strength
winners = sorted(winners, key=lambda f: (f.strength))

# iterate though the winning carriers distributing damage fairly
damage_to_distribute = int(damage)
for winner in winners:
    if not damage_to_distribute or winner.strength < 1: continue
    winners_damage = int(math.floor(damage / (winner_total_strength / winner.strength)))

    # if this winners damage is more that what is left to be distributed,
    # reduce it.
    if damage_to_distribute < winners_damage:
        winners_damage = damage_to_distribute

    if winner.strength < winners_damage:
        damage_to_distribute -= winners.strength
        winner.strength = 0
    else:
        winner.strength -= winners_damage
        damage_to_distribute -= winners_damage

# handle the case where rounding meant that not all damage was dealt
while damage_to_distribute > 0:
    for winner in winners:
        if damage_to_distribute <= 0:
            break
        if winner.strength > 0:
            # don't allow any strength to go lower than 0
            winner.strength -= 1
        damage_to_distribute -= 1

damage goes to the largest carrier first.

the best way to ensure carriers survive is to get them out of there!

sorry I was not clear, 2 enemies meeting on a third players star.

right, sorry I have limited code reading ablility.
so having one carrier collect all of a stars garrison will likely avoid the majority of carrier losses.

so for example, multiple defending carriers for player 1 are arriving at a star controlled.by player 1,
call these carriers X Y and Z all of them have 15 ships.
there are NO ships garrisoned to the star.
they arrive at the same time as single attacking carrier from player 2 who has 20 ships.
P1 has ordered X and Y to drop all ships, and Z to collect all.
XYZ successfully defends the planet by a comfortable margin and the attacking fleet has done 17 ships of damage.

are P1 carrier losses calculated against a single fleet of 45 ships, resulting in no carrier loss.
or is it calculated against 3 fleets of 15 resulting in a single carrier loss
or did the drop commands for X+Y garrison the star with 28 ships leaving Z fleet fighting with 15 ships and XY with 1 ship each resulting in the destruction of all 3?

So using the combat calculator
defender has 45 ships and what weapons ? weapons 10 or less than or equal to weapons 20 ?
attacker has 20 ships and what weapons ? weapons 17 ?

give me a few minutes and let me read Jay’s code. . . .

I think that occurs after combat, not before.

well in the combat i posted the battle report showed the two carriers as only having 1 ship and 1 ship lost.
so the drop all function had occured, whether the report is generated after the combat or after the transfers I dont know