Esempio n. 1
0
def repair_fleet(input_fleet):
    """
    Have logistics ships do their job and repair other ships in the fleet
    """
    logistics = logi_subfleet(input_fleet)
    logi_shield = logistics[0]
    logi_armor = logistics[1]
    if (logi_shield == []) and (logi_armor == []):
        return input_fleet

    damaged_shield = []

    # this has a slight bug that ships can rep themselves
    # and a ship might get over repped, but that's actually intended

    # shield first
    for x in range(len(input_fleet)):
        if input_fleet[x].attributes.shield != input_fleet[x].schema.shield:
            damaged_shield.append(x)

    if damaged_shield != []:
        for ship in logi_shield:
            rep_target = random.choice(damaged_shield)
            input_fleet[rep_target] = Ship(
                input_fleet[rep_target].schema,
                ShipAttributes(
                    min(input_fleet[rep_target].schema.shield,
                        (input_fleet[rep_target].attributes.shield +
                         ship.schema.buffs.remote_shield_repair)),
                    input_fleet[rep_target].attributes.armor,
                    input_fleet[rep_target].attributes.hull,
                ),
                input_fleet[rep_target].debuffs,
            )

    damaged_armor = []

    #armor second
    for x in range(len(input_fleet)):
        if input_fleet[x].attributes.armor != input_fleet[x].schema.armor:
            damaged_armor.append(int(x))

    if damaged_armor != []:
        for ship in logi_armor:
            rep_target = random.choice(damaged_armor)
            input_fleet[rep_target] = Ship(
                input_fleet[rep_target].schema,
                ShipAttributes(
                    input_fleet[rep_target].attributes.shield,
                    min(input_fleet[rep_target].schema.armor,
                        (input_fleet[rep_target].attributes.armor +
                         ship.schema.buffs.remote_armor_repair)),
                    input_fleet[rep_target].attributes.hull,
                ),
                input_fleet[rep_target].debuffs,
            )

    return input_fleet
Esempio n. 2
0
def ship_attack(attacker_weapon, attacker_debuffs, victim_ship):
    """
    Do a ship attack.

    Apply the attacker's schema onto the victim_ship as an attack
    and return a new Ship object as the result.
    """

    if not is_ship_alive(victim_ship):
        # save us some time, it could be the same dead ship.
        return victim_ship

    if victim_ship.schema.is_structure:
        # strucutres should not be attacked during fleet fights
        # structure damage and destruction is another mechanic outside of fleet engagements
        raise ValueError(
            "Battle.ship_attack() encountered a structure as a victim_ship")

    debuffs = grab_debuffs(attacker_weapon, victim_ship)

    if attacker_weapon['firepower'] <= 0:
        # no weapons: damage doesn't need to be calculated, but debuffs do
        return Ship(
            victim_ship.schema,
            ShipAttributes(
                victim_ship.attributes.shield,
                victim_ship.attributes.armor,
                victim_ship.attributes.hull,
            ),
            debuffs,
        )

    damage = true_damage(attacker_weapon['firepower'],
                         attacker_weapon['weapon_size'],
                         victim_ship.schema.size, attacker_debuffs,
                         victim_ship.debuffs)
    if damage <= 0:
        #if damage modfiers change damage to 0 then victim takes no damage
        return Ship(
            victim_ship.schema,
            ShipAttributes(
                victim_ship.attributes.shield,
                victim_ship.attributes.armor,
                victim_ship.attributes.hull,
            ),
            debuffs,
        )

    shield = victim_ship.attributes.shield - damage
    armor = victim_ship.attributes.armor + min(shield, 0)
    hull = victim_ship.attributes.hull + min(armor, 0)
    return Ship(
        victim_ship.schema,
        ShipAttributes(max(0, shield), max(0, armor), max(0, hull)),
        debuffs,
    )
Esempio n. 3
0
    def test_is_alive(self):
        library = ShipLibraryMock()
        schema1 = library.get_ship_schemata('ship1')
        ship1 = Ship(schema1, ShipAttributes(10, 10, 100))
        ship2 = Ship(schema1, ShipAttributes(10, 10, 0))
        ship3 = Ship(schema1, ShipAttributes(10, 10, -1))  # lolwut

        self.assertTrue(battle.is_ship_alive(ship1))
        self.assertFalse(battle.is_ship_alive(ship2))
        self.assertFalse(battle.is_ship_alive(ship3))
Esempio n. 4
0
    def test_expand_fleet(self):
        library = ShipLibraryMock()
        schema = library.get_ship_schemata('ship1')
        ship_count = {"ship1": 5}
        answer = [
            Ship(schema, ShipAttributes(10, 10, 100)),
            Ship(schema, ShipAttributes(10, 10, 100)),
            Ship(schema, ShipAttributes(10, 10, 100)),
            Ship(schema, ShipAttributes(10, 10, 100)),
            Ship(schema, ShipAttributes(10, 10, 100)),
        ]

        result = battle.expand_fleet(ship_count, library)
        self.assertEqual(answer, result.ships)
Esempio n. 5
0
def prune_fleet(attack_result):
    """
    Prune an AttackResult of dead ships and restore shields/armor.
    Returns the pruned fleet and a count of ships.
    """

    fleet = []
    count = {}
    damage_taken = 0

    for ship in attack_result.damaged_fleet:
        if not ship.attributes.hull > 0:
            continue

        fleet.append(
            Ship(
                ship.schema,
                ShipAttributes(
                    min(ship.schema.shield,
                        (ship.attributes.shield +
                         ship.schema.buffs.local_shield_repair)),
                    min(ship.schema.armor,
                        (ship.attributes.armor +
                         ship.schema.buffs.local_armor_repair)),
                    ship.attributes.hull,
                ),
                ship.debuffs,
            ))
        count[ship.schema.name] = count.get(ship.schema.name, 0) + 1

    return Fleet(fleet, count)
Esempio n. 6
0
 def test_local_rep(self):
     random.seed(0)
     attacker = {
         "local_rep_test": 10,
     }
     defender = {
         "local_rep_test": 20,
     }
     rounds = 6
     library = ShipLibraryMock()
     battle_instance = Battle(attacker, defender, rounds, library)
     schema_rep = library.get_ship_schemata('local_rep_test')
     attack_result = AttackResult([], [
         Ship(schema_rep, ShipAttributes(100, 100, 100)),
         Ship(schema_rep, ShipAttributes(0, 0, 100)),
         Ship(schema_rep, ShipAttributes(10, 10, 0)),
         Ship(schema_rep, ShipAttributes(10, 10, 100)),
     ], 0, 0)
     expected_fleet = [
         Ship(schema_rep, ShipAttributes(100, 100, 100)),
         Ship(schema_rep, ShipAttributes(5, 5, 100)),
         Ship(schema_rep, ShipAttributes(15, 15, 100)),
     ]
     result = battle.prune_fleet(attack_result)
     self.assertEqual(result.ships, expected_fleet)
Esempio n. 7
0
 def test_repair_fleet_does_not_scramble(self):
     random.seed(0)
     library = ShipLibraryMock()
     schema_remote = library.get_ship_schemata('remote_rep_test')
     tattered_fleet = [
         Ship(schema_remote, ShipAttributes(0, 0, 100)),
         Ship(schema_remote, ShipAttributes(10, 10, 10)),
         Ship(schema_remote, ShipAttributes(100, 100, 100)),
         Ship(schema_remote, ShipAttributes(10, 10, 0)),
         Ship(schema_remote, ShipAttributes(99, 99, 100)),
     ]
     expected_fleet = [
         Ship(schema_remote, ShipAttributes(10, 0, 100)),
         Ship(schema_remote, ShipAttributes(10, 20, 10)),
         Ship(schema_remote, ShipAttributes(100, 100, 100)),
         Ship(schema_remote, ShipAttributes(20, 30, 0)),
         Ship(schema_remote, ShipAttributes(100, 100, 100)),
     ]
     result = battle.repair_fleet(tattered_fleet)
     self.assertEqual(result, expected_fleet)
Esempio n. 8
0
    def test_fleet_attack(self):
        # Test the result of the attacking fleet firing once on the defenders.
        # Check that the damage on the defenders is accurate to only being
        # fired on once.
        attacker = {
            "ship1": 5,
        }
        defender = {
            "ship1": 4,
        }
        rounds = 6
        library = ShipLibraryMock()
        battle_instance = Battle(attacker,
                                 defender,
                                 rounds,
                                 library,
                                 calculate=False)

        random.seed(1)
        result = battle.fleet_attack(
            battle_instance.attacker_fleet,
            battle_instance.defender_fleet,
            0  # round number
        )

        self.assertEqual(result.hits_taken, 5)
        self.assertEqual(result.damage_taken, 250)

        schema1 = library.get_ship_schemata('ship1')
        result = battle.prune_fleet(result)
        self.assertEqual(result.ships, [
            Ship(schema1, ShipAttributes(10, 0, 20)),
            Ship(schema1, ShipAttributes(10, 0, 70)),
            Ship(schema1, ShipAttributes(10, 0, 70)),
            Ship(schema1, ShipAttributes(10, 0, 70)),
        ])
        self.assertEqual(result.ship_count, {
            'ship1': 4,
        })
Esempio n. 9
0
def expand_fleet(ship_count, library):
    # for the listing of numbers of ship we need to expand to each ship
    # having it's own value for shield, armor, and hull

    # TO DO: Make sure fleet when expanded is ordered by size
    #     From smallest to largest to make explode chance and
    #     shield bounce effects work out properly.

    ships = []
    for ship_type in ship_count:
        schema = library.get_ship_schemata(ship_type)
        ships.extend([
            Ship(
                schema,  # it's just a pointer...
                ShipAttributes(schema.shield, schema.armor, schema.hull),
            ) for i in range(ship_count[ship_type])
        ])
    return Fleet(ships, ship_count)
Esempio n. 10
0
    def test_fleet_attack_empty(self):
        library = ShipLibraryMock()
        schema1 = library.get_ship_schemata('ship1')

        empty_fleet = battle.expand_fleet({}, library)
        solo_fleet = battle.expand_fleet({'ship1': 1}, library)

        # attacking nothing will have no rounds.
        result = battle.fleet_attack(empty_fleet, empty_fleet,
                                     0)  # 0 is the round number
        self.assertEqual(result.damaged_fleet, empty_fleet.ships)

        # attacking nothing will have no rounds (for now?).
        result = battle.fleet_attack(solo_fleet, empty_fleet,
                                     1)  # 0 is the round number
        self.assertEqual(result.damaged_fleet, empty_fleet.ships)

        # nothing attacking a fleet will still result in a round (for now?).
        result = battle.fleet_attack(empty_fleet, solo_fleet,
                                     2)  # 0 is the round number
        self.assertEqual(result.damaged_fleet, [
            Ship(schema1, ShipAttributes(10, 10, 100)),
        ])
Esempio n. 11
0
    def test_ship_attack(self):
        library = ShipLibraryMock()
        schema1 = library.get_ship_schemata('ship1')
        schema2 = library.get_ship_schemata('ship2')
        schema3 = library.get_ship_schemata('ship3')
        ship1 = Ship(schema1, ShipAttributes(10, 10, 100))
        ship2 = Ship(schema2, ShipAttributes(100, 100, 100))
        ship3 = Ship(schema3, ShipAttributes(100, 100, 100))

        random.seed(1)
        #ship_attack(attacker, victim)
        ship1_1 = battle.ship_attack(ship2.schema.weapons[0], ship2.debuffs,
                                     ship1)
        self.assertEqual(ship1_1, Ship(schema1, ShipAttributes(0, 0, 0)))

        ship2_1 = battle.ship_attack(ship1.schema.weapons[0], ship1.debuffs,
                                     ship2)
        self.assertEqual(ship2_1, Ship(schema2, ShipAttributes(50, 100, 100)))

        ship2_2 = battle.ship_attack(ship1.schema.weapons[0], ship1.debuffs,
                                     ship2_1)
        self.assertEqual(ship2_2, Ship(schema2, ShipAttributes(0, 100, 100)))
Esempio n. 12
0
    def test_prune_fleet(self):
        library = ShipLibraryMock()
        schema1 = library.get_ship_schemata('ship1')
        schema2 = library.get_ship_schemata('ship2')
        schema3 = library.get_ship_schemata('ship3')

        attack_result = AttackResult(
            [],
            [
                Ship(schema1, ShipAttributes(10, 5, 100)),
                Ship(schema1, ShipAttributes(0, 10, 100)),
                Ship(schema2, ShipAttributes(10, 10,
                                             0)),  # how is this possible?
                Ship(schema2, ShipAttributes(10, 10, 100)),
                Ship(schema2, ShipAttributes(0, 0, 10)),
                Ship(schema3, ShipAttributes(10, 0, 10)),
            ],
            0,
            0)

        expected_fleet = [
            Ship(schema1, ShipAttributes(10, 5, 100)),
            Ship(schema1, ShipAttributes(10, 10, 100)),
            Ship(schema2, ShipAttributes(100, 10, 100)),
            Ship(schema2, ShipAttributes(100, 0, 10)),
            Ship(schema3, ShipAttributes(0, 0, 10)),
            # balance is restored.
        ]

        expected_count = {
            'ship1': 2,
            'ship2': 2,
            'ship3': 1,
        }

        result = battle.prune_fleet(attack_result)
        self.assertEqual(result.ships, expected_fleet)
        self.assertEqual(result.ship_count, expected_count)