def setUp(self): # Setup self.test_disaster_controller = DisasterController() self.test_effort_controller = EffortController() self.player = Player() self.player.action = Action() self.player.city = City()
class TestDisasters(unittest.TestCase): def setUp(self): # Setup self.test_disaster_controller = DisasterController() self.test_effort_controller = EffortController() self.player = Player() self.player.action = Action() self.player.city = City() def test_reduce(self): # Create disasters test_disaster_list = list() for dis in {Fire(), Blizzard(), Monster()}: test_disaster_list.append(dis) self.player.disasters.append(dis) # Cheat the population to be higher than intended pop = 0 pop += GameStats.disaster_initial_efforts[DisasterType.fire] pop += GameStats.disaster_initial_efforts[DisasterType.blizzard] pop += GameStats.disaster_initial_efforts[DisasterType.monster] self.player.city.population = pop # Have player handle disasters for dis in self.player.disasters: if isinstance(dis, Fire): self.player.action.add_effort( dis, GameStats.disaster_initial_efforts[DisasterType.fire]) if isinstance(dis, Blizzard): self.player.action.add_effort( dis, GameStats.disaster_initial_efforts[DisasterType.blizzard]) if isinstance(dis, Monster): self.player.action.add_effort( dis, GameStats.disaster_initial_efforts[DisasterType.monster]) # Unhandled fire addition unhandled_fire = Fire() test_disaster_list.append(unhandled_fire) self.player.disasters.append(unhandled_fire) # Run controllers self.test_effort_controller.handle_actions(self.player) self.test_disaster_controller.handle_actions(self.player) # Test outcome for dis in test_disaster_list: if dis == unhandled_fire: self.assertEqual( dis.effort_remaining, GameStats.disaster_initial_efforts[DisasterType.fire]) self.assertEqual(dis.status, DisasterStatus.live) self.assertIn(dis, self.player.disasters) else: if dis.effort_remaining != 0: print(dis) self.assertEqual(dis.effort_remaining, 0) self.assertEqual(dis.status, DisasterStatus.dead) self.assertNotIn(dis, self.player.disasters)
def __init__(self): super().__init__() self.turn = 0 # Singletons first self.event_controller = EventController() self.fun_stat_controller = FunStatController() self.accumulative_controller = AccumulativeController() self.city_generator_controller = CityGeneratorController() self.decree_controller = DecreeController() self.destruction_controller = DestructionController() self.disaster_controller = DisasterController() self.effort_controller = EffortController() self.game_over = False
class TestSensors(unittest.TestCase): def setUp(self): self.test_effort_controller = EffortController() # Note: not a guaranteed success rate def test_legal_odds(self): test_odds = { DisasterType.fire: 0.0, DisasterType.tornado: 0.5, DisasterType.blizzard: 0.99, DisasterType.earthquake: 1.00, DisasterType.monster: 1.00, DisasterType.ufo: 0.0 } turn_ranges = dict() for turn in range(100): turn_ranges[turn] = calculate_sensor_ranges(test_odds) max_val = -0.01 min_val = 1.01 for sensors in turn_ranges.values(): for level in sensors.values(): for val in level.values(): if val > max_val: max_val = val if val < min_val: min_val = val self.assertGreaterEqual(1, max_val) self.assertLessEqual(0, min_val) def test_upgrade(self): # Setup player = Player() player.action = Action() player.city = City() player.city.population = 1000 fire_sensor = player.city.sensors[SensorType.fire] self.assertEqual(fire_sensor.level, SensorLevel.level_zero) player.action.add_effort(fire_sensor, 50) self.test_effort_controller.handle_actions(player) self.assertEqual(fire_sensor.level, SensorLevel.level_one) player.action = Action() player.action.add_effort(fire_sensor, 100) self.test_effort_controller.handle_actions(player) self.assertEqual(fire_sensor.level, SensorLevel.level_two) player.action = Action() player.action.add_effort(fire_sensor, 500) self.test_effort_controller.handle_actions(player) self.assertEqual(fire_sensor.level, SensorLevel.level_three)
def setUp(self): self.test_effort_controller = EffortController()
class MasterController(Controller): def __init__(self): super().__init__() self.turn = 0 # Singletons first self.event_controller = EventController() self.fun_stat_controller = FunStatController() self.accumulative_controller = AccumulativeController() self.city_generator_controller = CityGeneratorController() self.decree_controller = DecreeController() self.destruction_controller = DestructionController() self.disaster_controller = DisasterController() self.effort_controller = EffortController() self.game_over = False # Receives all clients for the purpose of giving them the objects they will control def give_clients_objects(self, client): client.city = City() client.team_name = client.code.team_name() client.city.city_name = client.code.city_name() city_type = client.code.city_type() self.city_generator_controller.handle_actions(client, city_type) # Generator function. Given a key:value pair where the key is the identifier for the current world and the value is # the state of the world, returns the key that will give the appropriate world information def game_loop_logic(self, start=1): self.turn = start # Basic loop from 1 to max turns while True: # Wait until the next call to give the number yield self.turn # Increment the turn counter by 1 self.turn += 1 # If the next turn number is above the max, the iterator ends if self.turn > config.MAX_TURNS: break # Receives world data from the generated game log and is responsible for interpreting it def interpret_current_turn_data(self, client, world, turn): # Turn disaster occurrence into a real disaster for disaster in world['disasters']: d = disaster['disaster'] l = disaster['level'] dis = None if d is DisasterType.earthquake: dis = Earthquake(l) elif d is DisasterType.fire: dis = Fire(l) elif d is DisasterType.blizzard: dis = Blizzard(l) elif d is DisasterType.monster: dis = Monster(l) elif d is DisasterType.tornado: dis = Tornado(l) elif d is DisasterType.ufo: dis = Ufo(l) if dis is None: raise TypeError( f'Attempt to create disaster failed because given type: {disaster}, does not exist.' ) client.disasters.append(dis) self.fun_stat_controller.total_disasters += 1 self.event_controller.add_event({ "event_type": EventType.disaster_spawned, "turn": turn, "disaster": dis.to_json() }) # Run decrees immediately after disasters are generated (before player has a chance to set a new one) self.decree_controller.execute_decree(client) # read the sensor results from the game map, converting strings to ints and/or floats world['sensors'] = { int(key): {int(key2): float(val2) for key2, val2 in val.items()} for key, val in world['sensors'].items() } # give client their corresponding sensor odds for sensor in client.city.sensors.values(): sensor.sensor_results = world['sensors'][sensor.sensor_type][ sensor.level] # Accumulations should occur before the player takes their turn self.accumulative_controller.update(client) # Receive a specific client and send them what they get per turn. Also obfuscates necessary objects. def client_turn_arguments(self, client, world, turn): actions = Action() client.action = actions obfuscated_city = deepcopy(client.city) obfuscated_city.obfuscate() for building in obfuscated_city.buildings.values(): building.obfuscate() for sensor in obfuscated_city.sensors.values(): sensor.obfuscate() obfuscated_disasters = deepcopy(client.disasters) for disaster in obfuscated_disasters: disaster.obfuscate() args = ( self.turn, actions, obfuscated_city, obfuscated_disasters, ) return args # Perform the main logic that happens per turn def turn_logic(self, client, world, turn): self.event_controller.update(turn) self.effort_controller.handle_actions(client) self.decree_controller.update_decree(client.action.get_decree()) self.destruction_controller.handle_actions(client) self.disaster_controller.handle_actions(client) # Fun stat controller interjection self.fun_stat_controller.total_population_ever += client.city.population self.fun_stat_controller.total_structure_ever += client.city.structure if client.city.structure <= 0: self.print("Game is ending because city has been destroyed.") self.game_over = True if client.city.population <= 0: self.print("Game is ending because population has died.") self.game_over = True # Return serialized version of game def create_turn_log(self, client, world, turn): data = dict() # Retrieve all events on this turn data['events'] = [ event for event in self.event_controller.get_events() if event.get('turn') == turn ] data['rates'] = world['rates'] data['player'] = client.to_json() return data # Gather necessary data together in results file def return_final_results(self, client, world, turn): # data is the json information what will be written to the results file data = { "Team": client. team_name, # TODO: Replace with an engine-safe ID of each team "Score": turn, "Events": self.event_controller.get_events(), "Error": client.error, "Statistics": self.fun_stat_controller.export() } return data # Return if the game should be over def game_over_check(self): return self.game_over
class TestEfforts(unittest.TestCase): def setUp(self): self.test_effort_controller = EffortController() self.test_disaster_controller = DisasterController() self.player = Player() self.player.action = Action() self.player.city = City() def test_city(self): TEST_CITY_AMOUNT = 1 self.player.action.add_effort(self.player.city, TEST_CITY_AMOUNT) self.test_effort_controller.handle_actions(self.player) self.assertEqual( self.player.city.effort_remaining, GameStats.city_upgrade_cost[CityLevel.level_one] - TEST_CITY_AMOUNT) def test_sensor(self): TEST_SENSOR_AMOUNT = 1 for sensor_type in enum_iter(SensorType): self.player.action.add_effort( self.player.city.sensors[sensor_type], TEST_SENSOR_AMOUNT) self.test_effort_controller.handle_actions(self.player) for sensor in self.player.city.sensors.values(): self.assertEqual( sensor.effort_remaining, GameStats.sensor_upgrade_cost[SensorLevel.level_one] - TEST_SENSOR_AMOUNT) def test_population(self): TEST_POPULATION_AMOUNT = 20 self.player.city.population = 50 self.player.action.add_effort(ActionType.regain_population, TEST_POPULATION_AMOUNT) self.test_effort_controller.handle_actions(self.player) self.assertEqual( self.player.city.population, math.floor(GameStats.effort_population_multiplier * TEST_POPULATION_AMOUNT) + 50) def test_structure(self): TEST_STRUCTURE_AMOUNT = 20 self.player.city.structure = 0 self.player.action.add_effort(ActionType.repair_structure, TEST_STRUCTURE_AMOUNT) self.test_effort_controller.handle_actions(self.player) self.assertEqual( self.player.city.structure, math.floor(GameStats.effort_structure_multiplier * TEST_STRUCTURE_AMOUNT)) def test_disaster(self): TEST_DISASTER_AMOUNT = 1 test_disaster_list = list() for dis in {Fire(), Blizzard(), Monster()}: test_disaster_list.append(dis) self.player.disasters.append(dis) for dis in test_disaster_list: self.player.action.add_effort(dis, TEST_DISASTER_AMOUNT) self.test_effort_controller.handle_actions(self.player) for dis in test_disaster_list: self.assertEqual( dis.effort_remaining, GameStats.disaster_initial_efforts[dis.type] - TEST_DISASTER_AMOUNT)