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
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
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()
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
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()
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()
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()
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()
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
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
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
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
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()
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
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
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()
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
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
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
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()
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
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()
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()
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()
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()