コード例 #1
0
    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
コード例 #2
0
    def do_action(self, robot, args):
        '''Move the robot in the specified direction..

        @param robot: Instance of `objects.robot.Robot'.
        '''
        # Validating arguments.
        if len(args) != 2:
            raise InvalidArgumentsError(
                "Move action takes exactly two argument. {0} given.".format(
                    len(args)))

        direction = args[1]
        if not isinstance(direction,
                          str) or direction not in MoveAction.DIRECTIONS:
            raise InvalidArgumentsError(
                "Invalid direction passed to Move action.")

        robot_location = robot.get_location()
        direction_points = MoveAction.DIRECTIONS[direction]
        destination = (robot_location[0] + direction_points[0],
                       robot_location[1] + direction_points[1])

        try:
            self._do_move(robot, destination)
        except LockAlreadyAquiredError:
            # Waiting for a moment, and trying one more time.
            # Client shouldn't receive an error if, for example, someone updating a plant on these squares.
            self._logger.info("Concurrency when trying to move a robot.")
            time.sleep(0.02)
            self._do_move(robot, destination)
コード例 #3
0
    def do_action(self, robot, args):
        '''Makes robot eat the plant on the current location.

        @param robot: Instance of `objects.robot.Robot'.
        '''
        if len(args) != 1:
            raise InvalidArgumentsError("`eat' action takes no arguments.")

        try:
            current_square = self._world.get_square(robot.get_location(), for_update=True)
        except LockAlreadyAquiredError:
            # Trying one more time.
            time.sleep(0.02)
            current_square = self._world.get_square(robot.get_location(), for_update=True)

        plant = current_square.get_plant()

        if plant is None:
            raise NoPlantToEat("There's no plant on {0}".format(robot.get_location()))

        if plant.is_matured():
            robot.set_energy(robot.get_energy() + self._plant_energy)

        # Plant will be removed from the world, regardless of its maturity.
        current_square.set_plant(None)
コード例 #4
0
    def do_action(self, robot, args):
        '''Waters the square robot stands on.

        @param robot: Instance of `objects.robot.Robot'.
        '''
        if len(args) != 1:
            raise InvalidArgumentsError("`water' action takes no arguments.")

        if not robot.get_has_water():
            raise RobotHaveNoWaterError("Robot does not carry water.")

        try:
            square = self._world.get_square(robot.get_location(),
                                            for_update=True)
        except LockAlreadyAquiredError:
            # Waiting a little, and trying one more time.
            time.sleep(0.02)
            square = self._world.get_square(robot.get_location(),
                                            for_update=True)

        # Note: we don't raise an exception if there's no plant. A robot can waste its water.
        plant = square.get_plant()
        if plant is not None:
            plant.set_water_level(100)
            robot.set_honor(robot.get_honor() + 1)

        robot.set_has_water(False)
コード例 #5
0
    def do_action(self, robot, args):
        '''Returns information about the world..

        @param robot: Instance of `objects.robot.Robot'.
        '''
        if len(args) != 1:
            raise InvalidArgumentsError("`info' takes no arguments.")

        return self._result
コード例 #6
0
    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)))

        self._authenticator.authenticate_admin(password)

        if command == "map_data":
            return self._get_map_data(args)
コード例 #7
0
    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)
コード例 #8
0
    def do_action(self, robot, args):
        '''Plant a plant where robot stands.

        @param robot: Instance of `objects.robot.Robot'.
        '''
        if len(args) > 1:
            raise InvalidArgumentsError("`plant' action takes no arguments.")

        plant = Plant()

        self._world.plant(plant, robot.get_location())
コード例 #9
0
    def do_action(self, robot, args):
        '''Fill water tank of the robot.

        @param robot: Instance of `objects.robot.Robot'.
        '''
        if len(args) != 1:
            raise InvalidArgumentsError("`take_water' takes no arguments.")

        current_square = self._world.get_square(robot.get_location())

        if current_square.get_type() != MapSquareTypes.WATER:
            raise NoWaterError("There's no water on square {0}".format(
                robot.get_location()))

        robot.set_has_water(True)
コード例 #10
0
    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()
        }