def __init__(self):
        self._world = World()
        configs = Configs()

        self._result = {'world_size': '{0},{1}'.format(*self._world.get_size()),
                        'plant_max_age': configs.get_plant_max_age(),
                        'plant_matured_age': configs.get_plant_matured_age(),
                        'action_delay': configs.get_robots_actions_delay(),
                        'maximum_energy': configs.get_robots_maximum_energy(),
                        'birth_required_honor': configs.get_robots_birth_required_honor()}
    def __init__(self):
        self._world = World()
        configs = Configs()

        self._result = {
            'world_size': '{0},{1}'.format(*self._world.get_size()),
            'plant_max_age': configs.get_plant_max_age(),
            'plant_matured_age': configs.get_plant_matured_age(),
            'action_delay': configs.get_robots_actions_delay(),
            'maximum_energy': configs.get_robots_maximum_energy(),
            'birth_required_honor': configs.get_robots_birth_required_honor()
        }
    def test_not_enough_honor(self):
        '''Tests a robot with few honors, trying to give birth.'''
        population_control = PopulationControl()
        database = MemcachedDatabase()
        configs = Configs()

        robot = database.get_robot(TestGiveBirth.ROBOT_ID, for_update=True)
        robot.set_honor(configs.get_robots_birth_required_honor() - 1)
        database.commit()

        with self.assertRaises(NotEnoughHonorError):
            population_control.execute_command("123", "give_birth", [TestGiveBirth.ROBOT_ID])

        database.rollback()
    def test_info(self):
        '''Test received information.'''
        action = InfoAction()
        world = World()
        configs = Configs()
        robot = Robot("test_info_action_1293", "123")

        info = action.do_action(robot, [robot.get_id()])

        self.assertEqual(info['world_size'], '{0},{1}'.format(*world.get_size()))
        self.assertEqual(info['plant_max_age'], configs.get_plant_max_age())
        self.assertEqual(info['plant_matured_age'], configs.get_plant_matured_age())
        self.assertEqual(info['action_delay'], configs.get_robots_actions_delay())
        self.assertEqual(info['birth_required_honor'], configs.get_robots_birth_required_honor())
Beispiel #5
0
    def test_not_enough_honor(self):
        '''Tests a robot with few honors, trying to give birth.'''
        population_control = PopulationControl()
        database = MemcachedDatabase()
        configs = Configs()

        robot = database.get_robot(TestGiveBirth.ROBOT_ID, for_update=True)
        robot.set_honor(configs.get_robots_birth_required_honor() - 1)
        database.commit()

        with self.assertRaises(NotEnoughHonorError):
            population_control.execute_command("123", "give_birth",
                                               [TestGiveBirth.ROBOT_ID])

        database.rollback()
    def test_ok(self):
        '''Tests a valid situation.'''
        population_control = PopulationControl()
        database = MemcachedDatabase()
        configs = Configs()

        robot = database.get_robot(TestGiveBirth.ROBOT_ID, for_update=True)
        robot.set_honor(configs.get_robots_birth_required_honor() + 1)
        database.commit()

        new_password = population_control.execute_command("123", "give_birth", [TestGiveBirth.ROBOT_ID])
        database.commit()

        updated_robot = database.get_robot(TestGiveBirth.ROBOT_ID, for_update=False)

        self.assertEqual(updated_robot.get_honor(), 1)
        self.assertTrue(isinstance(new_password, str))
        self.assertEqual(len(new_password), 16)
Beispiel #7
0
    def test_info(self):
        '''Test received information.'''
        action = InfoAction()
        world = World()
        configs = Configs()
        robot = Robot("test_info_action_1293", "123")

        info = action.do_action(robot, [robot.get_id()])

        self.assertEqual(info['world_size'],
                         '{0},{1}'.format(*world.get_size()))
        self.assertEqual(info['plant_max_age'], configs.get_plant_max_age())
        self.assertEqual(info['plant_matured_age'],
                         configs.get_plant_matured_age())
        self.assertEqual(info['action_delay'],
                         configs.get_robots_actions_delay())
        self.assertEqual(info['birth_required_honor'],
                         configs.get_robots_birth_required_honor())
Beispiel #8
0
    def test_ok(self):
        '''Tests a valid situation.'''
        population_control = PopulationControl()
        database = MemcachedDatabase()
        configs = Configs()

        robot = database.get_robot(TestGiveBirth.ROBOT_ID, for_update=True)
        robot.set_honor(configs.get_robots_birth_required_honor() + 1)
        database.commit()

        new_password = population_control.execute_command(
            "123", "give_birth", [TestGiveBirth.ROBOT_ID])
        database.commit()

        updated_robot = database.get_robot(TestGiveBirth.ROBOT_ID,
                                           for_update=False)

        self.assertEqual(updated_robot.get_honor(), 1)
        self.assertTrue(isinstance(new_password, str))
        self.assertEqual(len(new_password), 16)
    def test_robot_simulation(self):
        '''This test simulates a full game scenario.'''
        database = MemcachedDatabase()
        world = World()
        configs = Configs()

        print()
        print("Simulating a robot playing the game. This may take a while.")

        # Creating a world for the robot to live in.
        # The world map is:
        #
        #    000000
        #    000222
        #    000144
        #    000144

        row01 = [
            MapSquare(MapSquareTypes.SOIL, (0, 30)),
            MapSquare(MapSquareTypes.SOIL, (1, 30)),
            MapSquare(MapSquareTypes.SOIL, (2, 30)),
            MapSquare(MapSquareTypes.SOIL, (3, 30)),
            MapSquare(MapSquareTypes.SOIL, (4, 30)),
            MapSquare(MapSquareTypes.SOIL, (5, 30))
        ]
        row02 = [
            MapSquare(MapSquareTypes.SOIL, (0, 31)),
            MapSquare(MapSquareTypes.SOIL, (1, 31)),
            MapSquare(MapSquareTypes.SOIL, (2, 31)),
            MapSquare(MapSquareTypes.ROCK, (3, 31)),
            MapSquare(MapSquareTypes.ROCK, (4, 31)),
            MapSquare(MapSquareTypes.ROCK, (5, 31))
        ]
        row03 = [
            MapSquare(MapSquareTypes.SOIL, (0, 32)),
            MapSquare(MapSquareTypes.SOIL, (1, 32)),
            MapSquare(MapSquareTypes.SOIL, (2, 32)),
            MapSquare(MapSquareTypes.SAND, (3, 32)),
            MapSquare(MapSquareTypes.WATER, (4, 32)),
            MapSquare(MapSquareTypes.WATER, (5, 32))
        ]
        row04 = [
            MapSquare(MapSquareTypes.SOIL, (0, 33)),
            MapSquare(MapSquareTypes.SOIL, (1, 33)),
            MapSquare(MapSquareTypes.SOIL, (2, 33)),
            MapSquare(MapSquareTypes.SAND, (3, 33)),
            MapSquare(MapSquareTypes.WATER, (4, 33)),
            MapSquare(MapSquareTypes.WATER, (5, 33))
        ]

        database.add_square_row(row01)
        database.add_square_row(row02)
        database.add_square_row(row03)
        database.add_square_row(row04)

        # Creating parent of our robot.
        parent_robot = Robot("parent_robot_1982.345", "123", name="Parent")
        parent_robot.set_honor(configs.get_robots_birth_required_honor() + 1)
        world.add_robot(parent_robot, (2, 31))
        database.commit()

        # Giving birth to our hero.
        result = self.post_request({
            'command': 'give_birth',
            'password': '******',
            'args': ["parent_robot_1982.345"]
        })
        self.assertEqual(result['status'], 200, result)
        born_password = result['result']

        # Robot requests a born.
        result = self.post_request({
            'command': 'born',
            'password': born_password,
            'args': [parent_robot.get_id()]
        })
        self.assertEqual(result['status'], 200)
        robot_id = result['result']['robot_id']
        password = result['result']['password']

        # Getting status.
        result = self.post_request({
            'command': 'status',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        self.assertTrue(result['result']['alive'])
        self.assertFalse(result['result']['has_water'])
        self.assertEqual(result['result']['location'], "2,30")

        # Moving somewhere to plan a corp.
        # Note that parent robot is on the south. So, we have to turn around it.
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'W']
        })
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'S']
        })
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'S']
        })
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'E']
        })
        self.assertEqual(result['status'], 200, result)

        # We are at the location. Checking if its correct.
        result = self.post_request({
            'command': 'status',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        self.assertEqual(result['result']['location'], "2,32")

        # Planting a corp here.
        result = self.post_request({
            'command': 'plant',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)

        # Checking if it is planted.
        result = self.post_request({
            'command': 'sense',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        self.assertEqual(result['result']['2,32']['surface_type'],
                         MapSquareTypes.SOIL)
        self.assertIsNotNone(result['result']['2,32']['plant'])

        # Going to pick water.
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'E']
        })
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'E']
        })
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({
            'command': 'pick_water',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({
            'command': 'status',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        self.assertTrue(result['result']['has_water'])

        # Getting back to the plant location.
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'W']
        })
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'W']
        })
        self.assertEqual(result['status'], 200, result)

        # Watering
        result = self.post_request({
            'command': 'water',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)

        # Checking
        result = self.post_request({
            'command': 'sense',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        # It lost some water already.
        self.assertGreater(result['result']['2,32']['plant']['water_level'],
                           70)

        # Plant should be matured by now. Eating!
        result = self.post_request({
            'command': 'status',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        previous_energy = result['result']['energy']

        result = self.post_request({
            'command': 'eat',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({
            'command': 'status',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 200, result)
        self.assertGreater(result['result']['energy'], previous_energy)

        # Now, trying some bad moves!

        # Trying to plant on a sand.
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'E']
        })
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({
            'command': 'plant',
            'password': password,
            'args': [robot_id]
        })
        self.assertEqual(result['status'], 500, result)
        self.assertEqual(result['error_code'], 'CannotPlantHereError')

        # Trying to move to a rock.
        result = self.post_request({
            'command': 'move',
            'password': password,
            'args': [robot_id, 'N']
        })
        self.assertEqual(result['status'], 500, result)
        self.assertEqual(result['error_code'], 'LocationIsBlockedError')
    def test_robot_simulation(self):
        '''This test simulates a full game scenario.'''
        database = MemcachedDatabase()
        world = World()
        configs = Configs()

        print()
        print("Simulating a robot playing the game. This may take a while.")

        # Creating a world for the robot to live in.
        # The world map is:
        #
        #    000000
        #    000222
        #    000144
        #    000144

        row01 = [MapSquare(MapSquareTypes.SOIL, (0, 30)),
                 MapSquare(MapSquareTypes.SOIL, (1, 30)),
                 MapSquare(MapSquareTypes.SOIL, (2, 30)),
                 MapSquare(MapSquareTypes.SOIL, (3, 30)),
                 MapSquare(MapSquareTypes.SOIL, (4, 30)),
                 MapSquare(MapSquareTypes.SOIL, (5, 30))]
        row02 = [MapSquare(MapSquareTypes.SOIL, (0, 31)),
                 MapSquare(MapSquareTypes.SOIL, (1, 31)),
                 MapSquare(MapSquareTypes.SOIL, (2, 31)),
                 MapSquare(MapSquareTypes.ROCK, (3, 31)),
                 MapSquare(MapSquareTypes.ROCK, (4, 31)),
                 MapSquare(MapSquareTypes.ROCK, (5, 31))]
        row03 = [MapSquare(MapSquareTypes.SOIL, (0, 32)),
                 MapSquare(MapSquareTypes.SOIL, (1, 32)),
                 MapSquare(MapSquareTypes.SOIL, (2, 32)),
                 MapSquare(MapSquareTypes.SAND, (3, 32)),
                 MapSquare(MapSquareTypes.WATER, (4, 32)),
                 MapSquare(MapSquareTypes.WATER, (5, 32))]
        row04 = [MapSquare(MapSquareTypes.SOIL, (0, 33)),
                 MapSquare(MapSquareTypes.SOIL, (1, 33)),
                 MapSquare(MapSquareTypes.SOIL, (2, 33)),
                 MapSquare(MapSquareTypes.SAND, (3, 33)),
                 MapSquare(MapSquareTypes.WATER, (4, 33)),
                 MapSquare(MapSquareTypes.WATER, (5, 33))]

        database.add_square_row(row01)
        database.add_square_row(row02)
        database.add_square_row(row03)
        database.add_square_row(row04)

        # Creating parent of our robot.
        parent_robot = Robot("parent_robot_1982.345", "123", name="Parent")
        parent_robot.set_honor(configs.get_robots_birth_required_honor() + 1)
        world.add_robot(parent_robot, (2, 31))
        database.commit()

        # Giving birth to our hero.
        result = self.post_request({'command': 'give_birth',
                                    'password': '******',
                                    'args': ["parent_robot_1982.345"]})
        self.assertEqual(result['status'], 200, result)
        born_password = result['result']

        # Robot requests a born.
        result = self.post_request({'command': 'born',
                                    'password': born_password,
                                    'args': [parent_robot.get_id()]})
        self.assertEqual(result['status'], 200)
        robot_id = result['result']['robot_id']
        password = result['result']['password']

        # Getting status.
        result = self.post_request({'command': 'status',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        self.assertTrue(result['result']['alive'])
        self.assertFalse(result['result']['has_water'])
        self.assertEqual(result['result']['location'], "2,30")

        # Moving somewhere to plan a corp.
        # Note that parent robot is on the south. So, we have to turn around it.
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'W']})
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'S']})
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'S']})
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'E']})
        self.assertEqual(result['status'], 200, result)

        # We are at the location. Checking if its correct.
        result = self.post_request({'command': 'status',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        self.assertEqual(result['result']['location'], "2,32")

        # Planting a corp here.
        result = self.post_request({'command': 'plant',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)

        # Checking if it is planted.
        result = self.post_request({'command': 'sense',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        self.assertEqual(result['result']['2,32']['surface_type'], MapSquareTypes.SOIL)
        self.assertIsNotNone(result['result']['2,32']['plant'])

        # Going to pick water.
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'E']})
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'E']})
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({'command': 'pick_water',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({'command': 'status',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        self.assertTrue(result['result']['has_water'])

        # Getting back to the plant location.
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'W']})
        self.assertEqual(result['status'], 200, result)
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'W']})
        self.assertEqual(result['status'], 200, result)

        # Watering
        result = self.post_request({'command': 'water',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)

        # Checking
        result = self.post_request({'command': 'sense',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        # It lost some water already.
        self.assertGreater(result['result']['2,32']['plant']['water_level'], 70)

        # Plant should be matured by now. Eating!
        result = self.post_request({'command': 'status',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        previous_energy = result['result']['energy']

        result = self.post_request({'command': 'eat',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({'command': 'status',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 200, result)
        self.assertGreater(result['result']['energy'], previous_energy)

        # Now, trying some bad moves!

        # Trying to plant on a sand.
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'E']})
        self.assertEqual(result['status'], 200, result)

        result = self.post_request({'command': 'plant',
                                    'password': password,
                                    'args': [robot_id]})
        self.assertEqual(result['status'], 500, result)
        self.assertEqual(result['error_code'], 'CannotPlantHereError')

        # Trying to move to a rock.
        result = self.post_request({'command': 'move',
                                    'password': password,
                                    'args': [robot_id, 'N']})
        self.assertEqual(result['status'], 500, result)
        self.assertEqual(result['error_code'], 'LocationIsBlockedError')
Beispiel #11
0
class PopulationControl:
    '''Controls the population of the world. i.e. controlling if a robot
    can have a child, or gives birth to new robots.
    '''
    def __init__(self):
        self._authenticator = Authenticator()
        self._database = MemcachedDatabase()
        self._world = World()
        self._id_generator = IDGenerator()
        self._configs = Configs()

    def execute_command(self, password, command, args):
        '''Executes the specified command.'''
        if not isinstance(password, str):
            raise InvalidArgumentsError(
                "Expected {0} as password, found {1}.".format(
                    type(str), type(password)))

        if command == "born":
            return self._born(password, args)
        elif command == "give_birth":
            return self._give_birth(password, args)

    def _born(self, password, args):
        '''Gives birth to a robot for the first time.

        @param args: List of arguments.
            The first argument can be a parent robot. If provided, the
            new robot will be born software near its parent. If not, it
            will be born on a random place.
        '''
        parent_robot_id = None
        if len(args) > 0:
            parent_robot_id = args[0]

        if parent_robot_id is not None:
            if not isinstance(parent_robot_id, str):
                raise InvalidArgumentsError(
                    "`parent_robot_id' must be `str', not {0}".format(
                        type(parent_robot_id)))

            parent_robot = self._database.get_robot(parent_robot_id)
            born_location = parent_robot.get_location()
        else:
            world_size = self._world.get_size()
            born_location = (random.randint(0, world_size[0] - 1),
                             random.randint(0, world_size[1] - 1))

        robot_name = ""
        if len(args) == 2:
            robot_name = args[1]

        self._authenticator.authenticate_new_robot(password)

        new_robot = Robot(self._id_generator.get_robot_id(),
                          self._id_generator.get_password(),
                          name=robot_name)

        self._world.add_robot(new_robot, (born_location[0], born_location[1]))

        return {
            'robot_id': new_robot.get_id(),
            'password': new_robot.get_password()
        }

    def _give_birth(self, password, args):
        '''Checks if robot has the permission to give birth to a child.
        If so, it generates and returns a new password.
        '''
        if len(args) != 1:
            raise InvalidArgumentsError(
                "`give_birth' takes exactly one argument.")

        robot_id = args[0]
        if not isinstance(robot_id, str):
            raise InvalidArgumentsError(
                "Expected {0} as robot_id, found {1}".format(
                    type(str), type(args[0])))

        robot = self._database.get_robot(robot_id, for_update=True)

        required_honor = self._configs.get_robots_birth_required_honor()
        if robot.get_honor() < required_honor:
            raise NotEnoughHonorError(
                "Robot needs {0} honor to give birth, but has {1}.".format(
                    required_honor, robot.get_honor()))

        robot.set_honor(robot.get_honor() - required_honor)

        # This while is exists, to prevent generating duplicated passwords.
        while True:
            try:
                new_password = self._id_generator.get_password()
                self._database.add_password(new_password)
                break
            except DuplicatedPasswordError:  # pragma: no cover
                continue

        return new_password