def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        action: Optional[Action] = None

        key = event.sym
        modifier = event.mod

        player = self.engine.player

        if key == tcod.event.K_SPACE:
            return actions.TakeStairsAction(player)

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()
        elif key == tcod.event.K_m:
            return HistoryViewer(self.engine)
        elif key == tcod.event.K_g:
            action = PickupAction(player)
        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_SLASH:
            return LookHandler(self.engine)
        elif key == tcod.event.K_TAB:
            return ControlsEventHandler(self.engine)

        # Был нажат невалидный ключ.
        return action
Exemple #2
0
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        action: Optional[Action] = None

        key = event.sym

        player = self.engine.player

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()
        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)
        elif key == tcod.event.K_g:
            action = PickupAction(player)
        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)
        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)
        elif key == tcod.event.K_l:
            return LookHandler(self.engine)
        elif key == tcod.event.K_y:
            return actions.TakeStairsAction(player)

        # No valid key was pressed
        return action
    def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        action: Optional[Action] = None
        key = event.sym
        modifier = event.mod
        player = self.engine.player

        if key == tcod.event.K_PERIOD and modifier & (tcod.event.KMOD_LSHIFT |
                                                      tcod.event.KMOD_RSHIFT):
            return actions.TakeStairsAction(player)

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)
        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()
        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)
        elif key == tcod.event.K_g:
            action = PickupAction(player)

        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)
        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)
        elif key == tcod.event.K_SLASH:
            return LookHandler(self.engine)

        return action
Exemple #4
0
    def perform(self) -> None:
        """
        Check if this actor is in player's sight.
        Actor's self.active will to True after being seen once.
        """
        # active check
        self.check_active()

        # immobility check
        if self.parent.check_for_immobility():
            return WaitAction(self.parent).perform()

        # target check
        if self.target and self.owner:
            if self.target == self.owner:
                self.target = None
            elif self.target.ai:
                if self.target.ai.owner == self.owner:
                    self.target = None

        # return
        if self.alignment == "hostile" or self.alignment == "neutral" or self.alignment == "allied" or self.owner:
            return self.perform_hostile()
        elif self.alignment == "peaceful":
            return self.perform_peaceful()
Exemple #5
0
 def perform(self) -> None:
     # Revert AI back to original state once effect expires.
     if self.turns_remaining <= 0:
         self.engine.message_log.add_message(
             f"The {self.entity.name} is no longer confused.")
         self.entity.ai = self.previous_ai
     else:
         self.turns_remaining -= 1
         # pick a random direction
         direction_x, direction_y = random.choice([
             (-1, -1),  # NW
             (0, -1),  # N
             (1, -1),  # NE
             (-1, 0),  # W
             (1, 0),  # E
             (-1, 1),  # SW
             (0, 1),  # S
             (1, 1),  # SE
         ])
         # Chance to not hit allies.
         target_x = self.entity.x + direction_x,
         target_y = self.entity.y + direction_y
         target_entity = self.engine.game_map.get_blocking_entity_at_location(
             target_x, target_y)
         if not (target_entity is self.engine.player):
             # 50% chance of not hitting allies
             # TODO: Tie into allegiances, intelligence.
             r = random.random()
             if r <= 0.5:
                 return WaitAction(self.entity)
         return BumpAction(
             self.entity,
             direction_x,
             direction_y,
         ).perform()
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        action: Optional[Action] = None

        key = event.sym

        player = self.engine.player

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)
        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()
        elif key == tcod.event.K_v:
            self.engine.event_handler = HistoryViewer(self.engine)

        elif key == tcod.event.K_g:
            action = PickupAction(player)
        elif key == tcod.event.K_o:
            self.engine.event_handler = InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_d:
            self.engine.event_handler = InventoryDropHandler(self.engine)
        elif key == tcod.event.K_SLASH:
            self.engine.event_handler = LookHandler(self.engine)

        return action
Exemple #7
0
    def perform(self) -> None:
        '''
        - If not in the player's vision, wait until next turn.
        - If the player is right next to the enemy, attack the player.
        - If the player sees the enemy, but the enemy is too far away to attack, move closer to the player.
        '''
        target = self.engine.player
        dx = target.x - self.entity.x
        dy = target.y - self.entity.y
        distance = max(abs(dx), abs(dy))  # "Chevyshev" distance

        if self.engine.game_map.visible[self.entity.x, self.entity.y]:
            if distance <= 1:
                return MeleeAction(self.entity, dx, dy).perform()

            # Update the enemy's path to chase after the player
            self.path = self.get_path_to(target.x, target.y)

        if self.path:
            dest_x, dest_y = self.path.pop(0)
            return MovementAction(self.entity, dest_x - self.entity.x,
                                  dest_y - self.entity.y).perform()

        # Wait until the next turn
        return WaitAction(self.entity).perform()
Exemple #8
0
def player_act(player, level, game):
    command = game.get_command()

    if command.name == Command.MOVE:
        return MoveAction(*command.data)
    elif command.name == Command.PICKUP:
        return PickupAction()
    elif command.name == Command.DROP:
        return DropAction()

    return WaitAction()
Exemple #9
0
 def idle_action(self) -> Action:
     """
     If the ai is not active, it will do nothing when its in idle state.
     If its active, it will wander around.
     Pets will follow its owner instead.
     """
     if self.owner:
         self.idle_action_pet()
     else:
         if self.active:
             if not self.path:
                 return self.wander()
         else:
             return WaitAction(self.parent).perform()
Exemple #10
0
def monster_act(monster, level, game):
    if monster.get(InFOV).in_fov:
        player = level.player
        monster_pos = monster.get(Position)
        player_pos = player.get(Position)
        distance = calc_distance(monster_pos.x, monster_pos.y, player_pos.x,
                                 player_pos.y)
        if distance < 2:
            return AttackAction(player)
        else:
            dx = int(round((player_pos.x - monster_pos.x) / distance))
            dy = int(round((player_pos.y - monster_pos.y) / distance))
            return MoveAction(dx, dy)

    return WaitAction()
Exemple #11
0
    def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        super().ev_keydown(event)
        action: Optional[Action] = None

        key = event.sym
        modifier = event.mod

        player = self.engine.player

        if key == tcod.event.K_PERIOD and modifier & (tcod.event.KMOD_LSHIFT |
                                                      tcod.event.KMOD_RSHIFT):
            return actions.TakeStairsAction(player)

        # If fullscreen was toggled, keep input handler active
        if event.sym == tcod.event.K_RETURN and event.mod & tcod.event.KMOD_ALT:
            self.engine.toggle_fullscreen()
            return None

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)

        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()

        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)

        elif key == tcod.event.K_g:
            action = PickupAction(player)

        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)

        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)

        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)

        elif key == tcod.event.K_m:
            return LookHandler(self.engine)

        return action
Exemple #12
0
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        action: Optional[Action] = None

        key = event.sym

        player = self.engine.player

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)
        elif key in ESCAPE_KEYS:
            action = EscapeAction(player)

        return action
Exemple #13
0
    def perform(self) -> None:
        target = self.engine.player
        dx = target.x - self.entity.x
        dy = target.y - self.entity.y
        distance = max(abs(dx), abs(dy))  # Chebyshev distance.

        if self.engine.game_map.visible[self.entity.x, self.entity.y]:
            if distance <= 1:
                return MeleeAction(self.entity, dx, dy).perform()
            self.path = self.get_path_to(target.x, target.y)

        if self.path:
            dest_x, dest_y = self.path.pop(0)
            return MovementAction(self.entity, dest_x - self.entity.x,
                                  dest_y - self.entity.y).perform()

        return WaitAction(self.entity).perform()
    def ev_keydown(self, event: str) -> Optional[ActionOrHandler]:
        action: Optional[Action] = None

        key = event
        modifier = event

        player = self.engine.player

        # if key == tcod.event.K_PERIOD and modifier & (
        #     tcod.event.KMOD_LSHIFT | tcod.event.KMOD_RSHIFT
        # ):

        if key == "spacebar":
            return actions.TakeStairsAction(player)
        if key == "numpad0":
            return actions.KillAllAction(player)
        if key == "numpadenter":
            return actions.SwitchViewMode(player)
        if key == "numpadadd":
            return actions.CheatTakeStairsAction(player)

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == "escape":
            raise SystemExit()
        elif key == "v":
            return HistoryViewer(self.engine)

        elif key == "g":
            action = PickupAction(player)

        elif key == "i":
            return InventoryActivateHandler(self.engine)
        elif key == "d":
            return InventoryDropHandler(self.engine)
        elif key == "c":
            return CharacterScreenEventHandler(self.engine)
        elif key == "/":
            return LookHandler(self.engine)

        # No valid key was pressed
        return action
Exemple #15
0
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        # action variable will hold whatever subclass of Action we assign it to, if no input it will store None
        action: Optional[Action] = None

        key = event.sym

        player = self.engine.player

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == tcod.event.K_ESCAPE:
            action = EscapeAction(player)

        return action
Exemple #16
0
   def perform(self) -> None:
       target = self.engine.player
       dx = target.x - self.entity.x
       dy = target.y - self.entity.y
       distance = max(abs(dx), abs(dy))  # Расстояние Чебышёва (максимум модуля разности компонент n-мерных числовых векторов)

       if self.engine.game_map.visible[self.entity.x, self.entity.y]:
           if distance <= 1:
               return MeleeAction(self.entity, dx, dy).perform()

           self.path = self.get_path_to(target.x, target.y)

       if self.path:
           dest_x, dest_y = self.path.pop(0)
           return MovementAction(
               self.entity, dest_x - self.entity.x, dest_y - self.entity.y,
           ).perform()

       return WaitAction(self.entity).perform()
Exemple #17
0
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        action: Optional[Action] = None

        key = event.sym

        # Common arguments for player actions.
        context = (self.engine, self.engine.player)

        if key in (tcod.event.K_UP, tcod.event.K_k):
            action = BumpAction(*context, dx=0, dy=-1)
        elif key in (tcod.event.K_DOWN, tcod.event.K_j):
            action = BumpAction(*context, dx=0, dy=1)
        elif key in (tcod.event.K_LEFT, tcod.event.K_h):
            action = BumpAction(*context, dx=-1, dy=0)
        elif key in (tcod.event.K_RIGHT, tcod.event.K_l):
            action = BumpAction(*context, dx=1, dy=0)

        elif key == tcod.event.K_y:
            action = BumpAction(*context, dx=-1, dy=-1)
        elif key == tcod.event.K_u:
            action = BumpAction(*context, dx=1, dy=-1)
        elif key == tcod.event.K_b:
            action = BumpAction(*context, dx=-1, dy=1)
        elif key == tcod.event.K_n:
            action = BumpAction(*context, dx=1, dy=1)

        elif key == tcod.event.K_PERIOD:
            action = WaitAction(*context)

        elif key == tcod.event.K_ESCAPE:
            action = EscapeAction(*context)

        elif key == tcod.event.K_g:
            action = PickupAction(*context)

        elif key == tcod.event.K_i:
            action = ShowInventoryAction(*context)

        elif key == tcod.event.K_d:
            action = ShowInventoryAction(*context, dropping=True)

        # No valid key was pressed
        return action
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        action: Optional[Action] = None

        key = event.sym

        player = self.engine.player

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        elif key == tcod.event.K_ESCAPE:
            action = EscapeAction(player)
        elif key == tcod.event.K_v:
            self.engine.event_handler = HistoryViewer(self.engine)

        # No valid key was pressed
        return action
Exemple #19
0
    def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        """ Registering af key presses.
         Returnerer type `None` hvis invalid key press.
         """

        action: Optional[Action] = None
        key = event.sym
        modifier = event.mod

        player = self.engine.player

        if key == tcod.event.K_PERIOD and modifier & (tcod.event.KMOD_LSHIFT |
                                                      tcod.event.KMOD_RSHIFT):
            return actions.TakeStairsAction(player)

        if key in MOVE_KEYS:
            dir_x, dir_y = MOVE_KEYS[key]
            action = BumpAction(player, dir_x, dir_y)
        elif key in WAIT_KEYS:
            action = WaitAction(player)
        # Exit the game
        elif key == tcod.event.K_ESCAPE:
            raise SystemExit(0)
        # Message Log
        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)
        # Pick up item
        elif key == tcod.event.K_g:
            action = PickUpAction(player)
        elif key == tcod.event.K_i:
            return InventoryActiveHandler(self.engine)
        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)
        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)
        elif key == tcod.event.K_MINUS:
            return LookHandler(self.engine)

        # Hvis en ikke valid tast blev trykket
        return action
Exemple #20
0
	def perform(self) -> None:
		target = self.engine.player
		dx = target.x - self.entity.x
		dy = target.y - self.entity.y
		distance = max(abs(dx), abs(dy))  # Chebyshev distance.

		# when the player is visible: if near player, attack!, if not, move towards it.
		if self.engine.game_map.visible[self.entity.x, self.entity.y]:
			if distance <= 1:
				return MeleeAction(self.entity, dx, dy).perform()

			self.path = self.get_path_to(target.x, target.y)

		# if there is a path, move one step.
		if self.path:
			dest_x, dest_y = self.path.pop(0)
			return MovementAction(
				self.entity, dest_x - self.entity.x, dest_y - self.entity.y,
			).perform()

		return WaitAction(self.entity).perform()
Exemple #21
0
    def take_turn(self, engine: Engine, target: Entity) -> Action:
        dx = target.x - self.parent.x
        dy = target.y - self.parent.y
        distance = math.sqrt(dx**2 + dy**2)

        dx = int(round(dx / distance))
        dy = int(round(dy / distance))

        action: Action = WaitAction(engine, self.parent)

        if engine.game_map.visible[self.parent.x, self.parent.y]:
            if distance >= 2:
                destination_x, destination_y = self.parent.get_first_step_towards_destination(
                    target.x, target.y, engine.game_map)
                action = MovementAction(engine, self.parent,
                                        destination_x - self.parent.x,
                                        destination_y - self.parent.y)
            else:
                action = MeleeAction(engine, self.parent, dx, dy)

        return action
Exemple #22
0
    def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        #action holds whatever subclass of Action we end up assigning it to. Defaults to none.
        action: Optional[Action] = None
        #key holds the actual key that we pressed
        key = event.sym
        modifier = event.mod
        player = self.engine.player

        if key == tcod.event.K_PERIOD and modifier & (tcod.event.KMOD_LSHIFT |
                                                      tcod.event.KMOD_RSHIFT):
            return actions.TakeStairsAction(player)
        #create a MovementAction for the up, down, left and right keys if any of them are pressed
        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)

        #if the user presses the escape key, return EscapeAction, which will exit the game. This will exit menus in the future
        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()

        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)

        elif key == tcod.event.K_e:
            action = PickupAction(player)

        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)
        elif key == tcod.event.K_SLASH:
            return LookHandler(self.engine)
        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)

        #Whether a valid key is pressed or not, we return the value of action, which is none by default.
        return action
Exemple #23
0
    def ev_keydown(self, event: tcod.event.KeyDown) -> Optional[Action]:
        # Set the default action to 'none' (returned when no key/invalid key is pressed)
        action: Optional[Action] = None

        # Capture the key pressed and grab the 'player' instance from the engine object
        key = event.sym
        player = self.engine.player

        # Check if keypress matches a valid keypress in the pre-defined Dict objects
        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)

        elif key in WAIT_KEYS:
            action = WaitAction(player)

        # The 'ESC' key returns an 'escape' action
        elif key == tcod.event.K_ESCAPE:
            action = EscapeAction(player)

        # Returns the resulting action type (defualt = 'none')
        return action
Exemple #24
0
    def perform(self) -> None:
        """Does what an hostile enemy does: when you see the player, move towards it and attack when in range"""
        target = self.engine.player
        dx = target.x - self.entity.x
        dy = target.y - self.entity.y
        distance = max(abs(dx), abs(dy))  # Chebyshev distance.

        if self.engine.game_map.visible[self.entity.x, self.entity.y]:
            if distance <= 1:
                return MeleeAction(self.entity, dx, dy).perform()

            self.path = self.get_path_to(target.x, target.y)

        if self.path:
            dest_x, dest_y = self.path.pop(0)
            return MovementAction(
                self.entity,
                dest_x - self.entity.x,
                dest_y - self.entity.y,
            ).perform()

        return WaitAction(self.entity).perform()
Exemple #25
0
    def ev_keydown(self,
                   event: tcod.event.KeyDown) -> Optional[ActionOrHandler]:
        action: Optional[Action] = None

        key = event.sym
        modifier = event.mod

        player = self.engine.player

        if key == tcod.event.K_PERIOD and modifier & (tcod.event.KMOD_LSHIFT |
                                                      tcod.event.KMOD_RSHIFT):
            if self.engine.game_world.current_floor == 8:
                return WinEventHandler(self.engine)
            else:
                return actions.TakeStairsAction(player)

        if key in MOVE_KEYS:
            dx, dy = MOVE_KEYS[key]
            action = BumpAction(player, dx, dy)
        elif key in WAIT_KEYS:
            action = WaitAction(player)
        elif key == tcod.event.K_ESCAPE:
            raise SystemExit()
        elif key == tcod.event.K_v:
            return HistoryViewer(self.engine)
        elif key == tcod.event.K_g:
            action = PickupAction(player)
        elif key == tcod.event.K_i:
            return InventoryActivateHandler(self.engine)
        elif key == tcod.event.K_d:
            return InventoryDropHandler(self.engine)
        elif key == tcod.event.K_c:
            return CharacterScreenEventHandler(self.engine)
        elif key == tcod.event.K_q:
            return ControlsScreenEventHandler(self.engine)

        # No valid key was pressed
        return action
Exemple #26
0
    def perform(self):
        target = self.engine.player
        dir_x = target.x - self.entity.x
        dir_y = target.y - self.entity.y
        distance = max(
            abs(dir_x),
            abs(dir_y))  # https://en.wikipedia.org/wiki/Chebyshev_distance

        # Prøve at angribe
        if self.engine.game_map.visible[self.entity.x, self.entity.y]:
            if distance <= 1:  # Hvis distancen mellem entity og target er 1 eller mindre (de rører hinanden)
                return MeleeAction(self.entity, dir_x, dir_y).perform()
            self.path = self.get_path_to(target.x, target.y)

        if self.path:  # Hvis entity har en path
            dest_x, dest_y = self.path.pop(0)  # Fjern den ældste entry
            return MovementAction(
                self.entity,
                dest_x - self.entity.x,
                dest_y - self.entity.y,
            ).perform()

        return WaitAction(self.entity).perform()
Exemple #27
0
    def perform(self) -> None:
        target = self.engine.player
        dx = target.x - self.entity.x
        dy = target.y - self.entity.y
        distance = max(
            abs(dx),
            abs(dy))  # Chebyshev distance, max distance over 2d matrix

        if self.engine.game_map.visible[self.entity.x,
                                        self.entity.y]:  #if T in field of view
            # if distance <= 1:
            #     return InitiateAction(self.entity, dx, dy).perform() #T cannot init to @; only @ to T

            self.path = self.get_path_to(target.x, target.y)

        if self.path:
            dest_x, dest_y = self.path.pop(0)
            return MovementAction(
                self.entity,
                dest_x - self.entity.x,
                dest_y - self.entity.y,
            ).perform()

        return WaitAction(self.entity).perform()
Exemple #28
0
    def perform_hunt(self):
        target = self.engine.player

        dx = target.x - self.entity.x
        dy = target.y - self.entity.y
        distance = max(abs(dx), abs(dy))  # Chebyshev distance.

        # wow this is a cheap trick. If the human can see me, then I act.
        # this is where the logic around ambient pathing goes, TBD.

        # for now, what needs to happen is we need to know if there's a current
        # uninterrupted sightline between the hostile and the player.
        # if yes, check if we're facing. if we are, fire. otherwise, rotate.
        # if self.engine.game_map.visible[self.entity.x, self.entity.y]:

        target_is_visible = self.is_visible(target.x, target.y)

        # reasons to drop a lock:
        #   moving
        #   target is out of sight
        #   target is out of range

        if target_is_visible:
            firing_direction = Facing.get_direction(self.entity.x,
                                                    self.entity.y, target.x,
                                                    target.y)

            if distance <= 1:
                self.entity.target_lock = None
                self.engine.message_log.add_message(
                    f"You got in close, enemy lost their lock!", color.white)
            elif distance > 1 and distance <= 24:
                # target lock now implies facing. if you move across a facing
                # boundary it doesn't unlock.
                if self.entity.target_lock == target:
                    return ShootAction(self.entity, target.x - self.entity.x,
                                       target.y - self.entity.y).perform()
                else:
                    # lets just assume we fully rotate to target immediately.
                    self.engine.message_log.add_message(
                        f"You've been locked on to!.", color.enemy_atk)

                    return TargetLockAction(self.entity, firing_direction,
                                            target).perform()

            else:
                # if they are visible but not in range, move to them.
                # lock is held in this case because they can see you they just know they can't hit you yet.

                # 8.18.20 -- actually, this should probably be change into SEARCH mode when that exists. Last known location. and also moving out of range but still being visible is a case we'll grapple with more when there's shotgun enemies. but that's a later problem.
                self.mode = HostileMode.PATROL
                self.entity.target_lock = None

                return WaitAction(self.entity).perform()
                self.path = self.get_path_to(target.x, target.y)
        else:

            # if target is not visibile, return to patrol.
            # eventually this should be a SEARCH variant.
            self.mode = HostileMode.PATROL
            self.entity.target_lock = None

            return WaitAction(self.entity).perform()
Exemple #29
0
    def perform(self) -> None:

        if self.mode == HostileMode.PATROL:
            # check if we happen to spot the player
            player_visible = self.is_visible(self.engine.player.x,
                                             self.engine.player.y)

            print(
                f'Patrolling to waypoint {self.waypoint} now at {(self.entity.x, self.entity.y)}'
            )

            if player_visible:
                print("SAW PLAYER, HUNTING")
                self.mode = HostileMode.HUNT
            else:
                if self.waypoint == None:
                    # we need to set a new waypoint.
                    self.path = []
                    tx = 0
                    ty = 0

                    while len(self.path) == 0:
                        tx = int(random() * self.engine.game_map.width)
                        ty = int(random() * self.engine.game_map.height)

                        self.path = self.get_path_to(tx, ty)
                        # print(f'setting path: {self.path}')

                    self.waypoint = (tx, ty)

                if (self.waypoint[0] == self.entity.x) and (self.waypoint[1]
                                                            == self.entity.y):
                    print("Arrived at destination.")
                    self.waypoint = None

        elif self.mode == HostileMode.HUNT:
            return self.perform_hunt()
        else:
            print('Unhandled mode.')

        if self.path:
            dest_x, dest_y = self.path[0]

            moving_direction = Facing.get_direction(self.entity.x,
                                                    self.entity.y, dest_x,
                                                    dest_y)
            # print(f'checking facing: {(dest_x, dest_y)} direction {moving_direction} current facing {self.entity.facing}')

            if (moving_direction == self.entity.facing):
                # now pop it.
                self.path.pop(0)
                return MovementAction(
                    self.entity,
                    dest_x - self.entity.x,
                    dest_y - self.entity.y,
                ).perform()
            else:
                # print(f'returning rotate action to {moving_direction}')
                return RotateAction(self.entity, moving_direction).perform()

        return WaitAction(self.entity).perform()