def test_generate_summary_text(self): attacker = { "ship2": 25, } defender = { "ship1": 25, } max_rounds = 6 library = ShipLibraryMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) #Ships in order of smallest first output_lines = """\ Attacker: ship2: 25 Defender: ship1: 25 Result: Attacker: ship2: 25 (Lost: 0) Defender: ALL DEFENDING SHIPS DESTROYED""" self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_summary_text_lists_all_ships(self): attacker = {"Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60} defender = {"Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60} max_rounds = 19 library = ShipLibraryOrderMock() random.seed(2) battle_instance = Battle(attacker, defender, max_rounds, library) output_lines = "Attacker:\n" +\ " Incursus: 60\n" +\ " Rifter: 60\n" +\ " Maller: 60\n" +\ " Moa: 60\n" +\ "Defender:\n" +\ " Incursus: 60\n" +\ " Rifter: 60\n" +\ " Maller: 60\n" +\ " Moa: 60\n" +\ "\n" +\ "Result:\n" +\ "Attacker:\n" +\ " Incursus: 4 (Lost: 56)\n" +\ " Rifter: 9 (Lost: 51)\n" +\ " Maller: 0 (Lost: 60)\n" +\ " Moa: 1 (Lost: 59)\n" +\ "Defender:\n" +\ " ALL DEFENDING SHIPS DESTROYED" self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_generate_summary_text(self): attacker = { "ship2": 25, } defender = { "ship1": 25, } max_rounds = 6 library = ShipLibraryMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) #Ships in order of smallest first output_lines = "Attacker:\n" +\ " ship2: 25\n" +\ "Defender:\n" +\ " ship1: 25\n" +\ "\n" +\ "Result:\n" +\ "Attacker:\n" +\ " ship2: 25 (Lost: 0)\n" +\ "Defender:\n" +\ " ALL DEFENDING SHIPS DESTROYED" self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_generate_summary_data(self): attacker = { "ship2": 25, } defender = { "ship1": 25, # they look pretty dead. ship2 too stronk } max_rounds = 6 library = ShipLibraryMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) self.assertEqual(battle_instance.defender_fleet.ships, []) self.assertEqual(len(battle_instance.round_results), 2) counts = [(a.ship_count, d.ship_count) for a, d in battle_instance.round_results] self.assertEqual(counts, [({ 'ship2': 25 }, { 'ship1': 9 }), ({ 'ship2': 25 }, {})]) shots = [(a.hits_taken, d.hits_taken) for a, d in battle_instance.round_results] self.assertEqual(shots, [(25, 25), (9, 25)]) damage = [(a.damage_taken, d.damage_taken) for a, d in battle_instance.round_results] self.assertEqual(damage, [(1250, 1920), (450, 1080)]) summary = battle_instance.generate_summary_data() summary_test = { "attacker_fleet": { "ship2": 25 }, "defender_fleet": { "ship1": 25 }, "attacker_result": { "ship2": 25 }, "attacker_losses": { "ship2": 0 }, "attacker_shots_fired": 50, "attacker_damage_dealt": 3_000, "defender_result": {}, "defender_losses": { "ship1": 25 }, "defender_shots_fired": 34, "defender_damage_dealt": 1_700 } self.assertEqual(summary, summary_test)
def test_order_of_generate_summary_text(self): attacker = { "Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60 } defender = { "Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60 } max_rounds = 6 library = ShipLibraryOrderMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) #Ships in order of smallest first output_lines = """\ Attacker: Incursus: 60 Rifter: 60 Maller: 60 Moa: 60 Defender: Incursus: 60 Rifter: 60 Maller: 60 Moa: 60 Result: Attacker: Incursus: 45 (Lost: 15) Rifter: 56 (Lost: 4) Maller: 46 (Lost: 14) Moa: 47 (Lost: 13) Defender: Incursus: 37 (Lost: 23) Rifter: 56 (Lost: 4) Maller: 45 (Lost: 15) Moa: 43 (Lost: 17)""" # "attacker_shots_fired": 1386, # "attacker_damage_dealt": 73691, # "defender_shots_fired": 1384, # "defender_damage_dealt": 71928} self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_generate_summary_data(self): attacker = { "ship2": 25, } defender = { "ship1": 25, # they look pretty dead. ship2 too stronk } max_rounds = 6 library = ShipLibraryMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) self.assertEqual(battle_instance.defender_fleet.ships, []) self.assertEqual(len(battle_instance.round_results), 2) counts = [(a.ship_count, d.ship_count) for a, d in battle_instance.round_results] self.assertEqual(counts, [ ({"ship2": 25}, {"ship1": 9}), ({"ship2": 25}, {}) ]) shots = [(a.hits_taken, d.hits_taken) for a, d in battle_instance.round_results] self.assertEqual(shots, [ (25, 25), (9, 25) ]) damage = [(a.damage_taken, d.damage_taken) for a, d in battle_instance.round_results] self.assertEqual(damage, [ (1250, 1920), (450, 1080) ]) summary = battle_instance.generate_summary_data() summary_test = { "attacker_fleet": {"ship2": 25}, "defender_fleet": {"ship1": 25}, "attacker_result": {"ship2": 25}, "attacker_losses": {"ship2": 0}, "attacker_shots_fired": 50, "attacker_damage_dealt": 3_000, "defender_result": {}, "defender_losses": {"ship1": 25}, "defender_shots_fired": 34, "defender_damage_dealt": 1_700 } self.assertEqual(summary, summary_test)
def test_attackers_get_ecm(self): # the test target has no sensor strength # so it will be perma-jammed # on round one it will nuke off all the armor of the attacker # but it will not be able to make a killing blow on round 2 # because it will be permajammed attacker = { "ewar_test_target": 1, } defender = { "ewar_ecm_test": 1, } rounds = 6 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library) schema_test = library.get_ship_schemata('ewar_ecm_test') schema_target = library.get_ship_schemata('ewar_test_target') #round_results => [0]th round, # [0]: attacker ([1]: defender) self.assertEqual(battle_instance.round_results[0][0].ship_count, {"ewar_test_target": 1}) self.assertEqual(battle_instance.round_results[0][1].ship_count, {"ewar_ecm_test": 1}) self.assertEqual(battle_instance.defender_result, { 'ewar_ecm_test': 1, }) self.assertEqual(battle_instance.attacker_result, {})
def test_priority_targets(self): random.seed(1) attacker = { "priority_test_ship": 1, } defender = {"priority_test_not_target": 1, "priority_test_target": 1} rounds = 2 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library) self.assertEqual(battle_instance.defender_fleet.ships, []) self.assertEqual(len(battle_instance.round_results), 2) counts = [(a.ship_count, d.ship_count) for a, d in battle_instance.round_results] self.assertEqual(counts, [({ 'priority_test_ship': 1 }, { 'priority_test_not_target': 1 }), ({ 'priority_test_ship': 1 }, {})]) shots = [(a.hits_taken, d.hits_taken) for a, d in battle_instance.round_results] self.assertEqual(shots, [(0, 1), (0, 1)]) damage = [(a.damage_taken, d.damage_taken) for a, d in battle_instance.round_results] self.assertEqual(damage, [(0, 300), (0, 300)])
def test_calculate_battle(self): attacker = { "ship2": 25, } defender = { "ship1": 25, # they look pretty dead. ship2 too stronk } max_rounds = 6 random.seed(0) library = ShipLibraryMock() battle_instance = Battle(attacker, defender, max_rounds, library) self.assertEqual(battle_instance.defender_fleet.ships, []) self.assertEqual(len(battle_instance.round_results), 2) counts = [(a.ship_count, d.ship_count) for a, d in battle_instance.round_results] self.assertEqual(counts, [({ 'ship2': 25 }, { 'ship1': 9 }), ({ 'ship2': 25 }, {})]) shots = [(a.hits_taken, d.hits_taken) for a, d in battle_instance.round_results] self.assertEqual(shots, [(25, 25), (9, 25)]) damage = [(a.damage_taken, d.damage_taken) for a, d in battle_instance.round_results] self.assertEqual(damage, [(1_250, 1_920), (450, 1_080)])
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)
def test_calculate_round(self): random.seed(0) attacker = { "ship1": 15, "ship2": 1_000, } defender = { "ship1": 8, # they look pretty dead. } rounds = 6 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library, calulate=False) random.seed(0) battle_instance.calculate_round(0) # round number self.assertEqual(battle_instance.defender_fleet.ships, [])
def test_order_of_generate_summary_text(self): attacker = {"Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60} defender = {"Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60} max_rounds = 6 library = ShipLibraryOrderMock() random.seed(0) battle_instance = Battle(attacker, defender, max_rounds, library) #Ships in order of smallest first output_lines = "Attacker:\n" +\ " Incursus: 60\n" +\ " Rifter: 60\n" +\ " Maller: 60\n" +\ " Moa: 60\n" +\ "Defender:\n" +\ " Incursus: 60\n" +\ " Rifter: 60\n" +\ " Maller: 60\n" +\ " Moa: 60\n" +\ "\n" +\ "Result:\n" +\ "Attacker:\n" +\ " Incursus: 45 (Lost: 15)\n" +\ " Rifter: 56 (Lost: 4)\n" +\ " Maller: 46 (Lost: 14)\n" +\ " Moa: 47 (Lost: 13)\n" +\ "Defender:\n" +\ " Incursus: 37 (Lost: 23)\n" +\ " Rifter: 56 (Lost: 4)\n" +\ " Maller: 45 (Lost: 15)\n" +\ " Moa: 43 (Lost: 17)" # 'attacker_fleet': {'Rifter': 60, 'Incursus': 60, 'Maller': 60, 'Moa': 60}, # 'defender_fleet': {'Rifter': 60, 'Incursus': 60, 'Maller': 60, 'Moa': 60}, # 'attacker_result': {'Rifter': 56, 'Incursus': 45, 'Maller': 46, 'Moa': 47}, # 'attacker_losses': {'Rifter': 4, 'Incursus': 15, 'Maller': 14, 'Moa': 13}, # 'attacker_shots_fired': 1386, # 'attacker_damage_dealt': 73691, # 'defender_result': {'Rifter': 56, 'Incursus': 37, 'Maller': 45, 'Moa': 43}, # 'defender_losses': {'Rifter': 4, 'Incursus': 23, 'Maller': 15, 'Moa': 17}, # 'defender_shots_fired': 1384, # 'defender_damage_dealt': 71928} self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_multiple_weapons(self): # one ship has 3 weapons with 100 damage each # the other has 1 weapon with 500 damage # both ships should destroy each other random.seed(0) attacker = { "multiple_weapon_test": 1, } defender = { "ship2": 1, } rounds = 1 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library, calculate=False) battle_instance.calculate_round(0) # round number self.assertEqual(battle_instance.defender_fleet.ships, []) self.assertEqual(battle_instance.attacker_fleet.ships, [])
def test_summary_text_lists_all_ships(self): attacker = { "Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60 } defender = { "Rifter": 60, "Incursus": 60, "Maller": 60, "Moa": 60 } max_rounds = 19 library = ShipLibraryOrderMock() random.seed(2) battle_instance = Battle(attacker, defender, max_rounds, library) output_lines = """\ Attacker: Incursus: 60 Rifter: 60 Maller: 60 Moa: 60 Defender: Incursus: 60 Rifter: 60 Maller: 60 Moa: 60 Result: Attacker: Incursus: 4 (Lost: 56) Rifter: 9 (Lost: 51) Maller: 0 (Lost: 60) Moa: 1 (Lost: 59) Defender: ALL DEFENDING SHIPS DESTROYED""" self.assertEqual(output_lines, battle_instance.generate_summary_text())
def test_calculate_battle_stalemate(self): random.seed(0) # too much shield and shield recharge haha. stalemates = { "ship4": 3, } rounds = 6 library = ShipLibraryMock() battle_instance = Battle(stalemates, stalemates, rounds, library) self.assertEqual(len(battle_instance.round_results), 6) for a, d in battle_instance.round_results: self.assertEqual(a.ship_count, stalemates) self.assertEqual(a.hits_taken, 3) self.assertEqual(a.damage_taken, 750_000) self.assertEqual(d.ship_count, stalemates) self.assertEqual(d.hits_taken, 3) self.assertEqual(d.damage_taken, 750_000)
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, })
def test_aoe_weapon(self): random.seed(0) attacker = { "area_of_effect_test": 1, } defender = { "ship1": 3, } rounds = 1 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library) #round_results => [0]th round, # [0]: attacker ([1]: defender) self.assertEqual(battle_instance.round_results[0][0].ship_count, {"area_of_effect_test": 1}) self.assertEqual(battle_instance.round_results[0][1].ship_count, {}) self.assertEqual(battle_instance.attacker_result, { 'area_of_effect_test': 1, }) self.assertEqual(battle_instance.defender_result, {})
def test_ewar_ecm_battle2(self): # the test target has low sensor strength # so it will be perma-jammed # on round one it will nuke off all the armor of the attacker # but it will not be able to make a killing blow on round 2 # because it will be permajammed random.seed(1) attacker = { "ewar_ecm_test": 1, } defender = { "ewar_test_target2": 1, } rounds = 6 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library) schema_test = library.get_ship_schemata('ewar_ecm_test') schema_target = library.get_ship_schemata('ewar_test_target') self.assertEqual(battle_instance.attacker_result, { 'ewar_ecm_test': 1, }) self.assertEqual(battle_instance.defender_result, {})
def test_fleet_attack_damage_limited_by_hp(self): random.seed(0) attacker = { "ship4": 1, } defender = { "ship1": 1, } rounds = 6 library = ShipLibraryMock() battle_instance = Battle(attacker, defender, rounds, library, calculate=False) attack_result = battle.fleet_attack( battle_instance.attacker_fleet, battle_instance.defender_fleet, 0 # round number ) self.assertEqual(attack_result.hits_taken, 1) self.assertEqual(attack_result.damage_taken, 120)
def run(): parser = argparse.ArgumentParser( description='IdleISS: The Internet Spaceships IdleRPG') parser.add_argument( '-u', '--universe', default=default_universe_config, dest='uniconfig', action='store', type=str, help= 'Set json universe settings file, if not provided the default {0} will be used' .format(default_universe_config)) parser.add_argument( '-s', '--ships', default=default_ships_config, dest='shipsconfig', action='store', type=str, help= 'Set json ships settings file, if not provided the default {0} will be used' .format(default_ships_config)) parser.add_argument( '--gen-maps', action='store_true', dest='genmaps', help='Generate the universe maps and put them in output/maps/ then exit' ) parser.add_argument( '--simulate-battle', default=None, dest='simbattle', const=example_fleet_fight, nargs='?', action='store', type=str, help= 'Simulate a fleet fight between two fleets using a file and exit. Example file: {0}' .format(example_fleet_fight)) parser.add_argument( '-q', '--quick', action='store_true', dest='quickrun', help='Do not run the interpreter, only verify config files') one_shot_only = False args = parser.parse_args() if args.uniconfig != default_universe_config: print(f'Generating universe using alternate config: {args.uniconfig}') uni = Universe(args.uniconfig) print(uni.debug_output) print(f'Universe successfully loaded from {args.uniconfig}') if args.shipsconfig != default_ships_config: print(f'Loading starships using alternate config: {args.shipsconfig}') library = ShipLibrary(args.shipsconfig) print(f'Starships successfully loaded from {args.shipsconfig}: ') print(f'\tImported {len(library.ship_data)} ships') # map generation if args.genmaps: one_shot_only = True if not os.path.exists('output/maps'): os.makedirs('output/maps') print('\nGenerating region map and regional maps in /output/maps:') print(' generating {0} files:'.format(len(uni.regions) + 1)) region_graph = uni.generate_networkx(uni.regions) uni.save_graph(region_graph, 'output/maps/default_regions.png') print('=', end='', flush=True) for region in uni.regions: system_list = [] for constellation in region.constellations: system_list.extend(constellation.systems) inter_region_graph = uni.generate_networkx(system_list) uni.save_graph( inter_region_graph, f'output/maps/default_region_{str(region.name)}.png') print('=', end='', flush=True) print('') # battle simulation if args.simbattle: one_shot_only = True #this must be a one_shot_due to random being reseeded random.seed() print(f'\nSimulating fleet fight using {args.simbattle}') raw_data = {} with open(args.simbattle) as fd: raw_data = json.load(fd) if type(raw_data) != dict: raise ValueError( '--simulate-battle was not passed a json dictionary') battle_instance = Battle(raw_data['attacker'], raw_data['defender'], raw_data['rounds'], library) print(str(battle_instance.generate_summary_text())) print(f'\nBattle lasted {len(battle_instance.round_results)} rounds.') if not one_shot_only and not args.quickrun: # execute interpreter interp = Interpreter(args.uniconfig, args.shipsconfig) interp.run() # one_shot_only is True or interpreter has exited print('\nIdleISS exiting')
def run(): parser = argparse.ArgumentParser(description="IdleISS: The Internet Spaceships IdleRPG") parser.add_argument("-u", "--universe", default=default_universe_config, dest="uniconfig", action="store", type=str, help=f"Set json universe settings file, if not provided the default {default_universe_config} will be used") parser.add_argument("-s", "--ships", default=default_ships_config, dest="shipsconfig", action="store", type=str, help=f"Set json ships settings file, if not provided the default {default_ships_config} will be used") parser.add_argument("--gen-maps", action="store_true", dest="genmaps", help="Generate the universe maps and put them in output/maps/ then exit") parser.add_argument("--simulate-battle", default=None, dest="simbattle", const=example_fleet_fight, nargs="?", action="store", type=str, help=f"Simulate a fleet fight between two fleets using a file and exit. Example file: {example_fleet_fight}") parser.add_argument("-q", "--quick", action="store_true", dest="quickrun", help="Do not run the interpreter, only verify config files") parser.add_argument("--preload", dest="interpreter_preload", action="store", type=str, help="if the interpreter is executed then this file will be used as the initial commands before control is " "given to the user") parser.add_argument("--log-interpreter", action="store_true", dest="interpreter_log_enable", help="Enable interpreter logs for future playback. Logs are stored in interpreter_log.txt") one_shot_only = False args = parser.parse_args() if args.uniconfig != default_universe_config: print(f"Generating universe using alternate config: {args.uniconfig}") uni = Universe(args.uniconfig) print(''.join(uni.debug_output)) print(f"Universe successfully loaded from {args.uniconfig}") if args.shipsconfig != default_ships_config: print(f"Loading starships using alternate config: {args.shipsconfig}") library = ShipLibrary(args.shipsconfig) print(f"Starships successfully loaded from {args.shipsconfig}: ") print(f"\tImported {len(library.ship_data)} ships") # map generation if args.genmaps: one_shot_only = True if not os.path.exists("output/maps"): os.makedirs("output/maps") print("\nGenerating region map and regional maps in /output/maps:") print(f" generating {len(uni.regions)+1} files:") region_graph = uni.generate_networkx(uni.regions) uni.save_graph(region_graph, "output/maps/default_regions.png") print("=", end="", flush=True) for region in uni.regions: system_list = [] for constellation in region.constellations: system_list.extend(constellation.systems) inter_region_graph = uni.generate_networkx(system_list) uni.save_graph(inter_region_graph, f"output/maps/default_region_{str(region.name)}.png") print("=", end="", flush=True) print("") # battle simulation if args.simbattle: one_shot_only = True # this must be a one_shot_due to random being reseeded random.seed() print(f"\nSimulating fleet fight using {args.simbattle}") raw_data = {} with open(args.simbattle) as fd: raw_data = json.load(fd) if type(raw_data) != dict: raise ValueError("--simulate-battle was not passed a json dictionary") battle_instance = Battle(raw_data["attacker"], raw_data["defender"], raw_data["rounds"], library) print(str(battle_instance.generate_summary_text())) print(f"\nBattle lasted {len(battle_instance.round_results)} rounds.") if not one_shot_only and not args.quickrun: # execute interpreter interp = Interpreter(args.uniconfig, args.shipsconfig) log_enable = False if args.interpreter_log_enable: log_enable = True if args.interpreter_preload: interp.run(preload_file=args.interpreter_preload, logs_enabled=log_enable) else: interp.run(logs_enabled=log_enable) # one_shot_only is True or interpreter has exited print("\nIdleISS exiting")
def fight(self, attacker, defender, seed=0, rounds=6): random.seed(seed) result = Battle(attacker, defender, rounds, self.library) return result