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)
Example #3
0
    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()
Example #6
0
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
Example #7
0
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)