def use(self, item_entity, **kwargs): results = [] item_component = item_entity.item if item_component.use_function is None: equip_component = item_entity.equip if equip_component: results.append({'equip': item_entity}) else: results.append({ 'message': Message('The {0} cannot be used!'.format(item_entity.name), lc.yellow) }) else: if item_component.targeting and not (kwargs.get('target_x') or kwargs.get('target_y')): results.append({'targeting': item_entity}) else: kwargs = {**item_component.function_kwargs, **kwargs} item_use_results = item_component.use_function( self.owner, **kwargs) for result in item_use_results: if result.get('consumed'): self.remove_item(item_entity) results.extend(item_use_results) return results
def cast_lightning(*args, **kwargs): caster = args[0] entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') damage = kwargs.get('damage') maximum_range = kwargs.get('maximum_range') results = [] target = None closest_distance = maximum_range + 1 for entity in entities: if entity.fighter and entity != caster and lc.map_is_in_fov( fov_map, entity.x, entity.y): distance = caster.distance_to(entity) if distance < closest_distance: target = entity closest_distance = distance if target: results.append({ 'consumed': True, 'target': target, 'message': Message('A lightning bolt strikes {0} for {1} damage.'.format( target.name, damage)) }) results.extend(target.fighter.take_damage(damage)) else: results.append({ 'consumed': False, 'target': None, 'message': Message('No enemy is close enough to strike.', lc.red) }) return results
def cast_confuse(*args, **kwargs): entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') results = [] if not lc.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message('You cannot target you cannot see.', lc.yellow) }) return results for entity in entities: if entity.x == target_x and entity.y == target_y and entity.ai: confused_ai = ConfusedMonster(entity.ai, 10) confused_ai.owner = entity entity.ai = confused_ai results.append({ 'consumed': True, 'message': Message( 'The eyes of the {0} look vacant as he begins to stumble around.' .format(entity.name), lc.green) }) break else: results.append({ 'consumed': False, 'message': Message('There is no targetable enemy at the location.', lc.yellow) }) return results
def add_item(self, item): results = [] if len(self.items) >= self.capacity: results.append({ 'item_added': None, 'message': Message('You cannot carry any more, your inventory is full.', lc.yellow) }) else: results.append({ 'item_added': item, 'message': Message('You pick up the {0}!'.format(item.name), lc.blue) }) self.items.append(item) return results
def kill_enemy(enemy): death_message = Message('{0} dies!'.format(enemy.name.capitalize()), lc.orange) enemy.char = '%' enemy.colour = lc.dark_red enemy.blocks = False enemy.fighter = None enemy.ai = None enemy.name = 'remains of ' + enemy.name enemy.render_order = RenderOrder.CORPSE return death_message
def cast_fireball(*args, **kwargs): entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') damage = kwargs.get('damage') radius = kwargs.get('radius') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') results = [] if not lc.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message('You cannot target a tile you can\'t see.', lc.yellow) }) return results results.append({ 'consumed': True, 'message': Message( 'The fireball explodes, burning everything within {0} tiles!'. format(radius), lc.orange) }) for entity in entities: if entity.distance(target_x, target_y) <= radius and entity.fighter: results.append({ 'message': Message( '{0} is burned for {1} damage.'.format( entity.name, damage), lc.orange) }) results.extend(entity.fighter.take_damage(damage)) return results
def heal(*args, **kwargs): entity = args[0] amount = kwargs.get('amount') results = [] if entity.fighter.health == entity.fighter.max_health: results.append({ 'consumed': False, 'message': Message('You are already at full health.', lc.yellow) }) else: entity.fighter.heal(amount) results.append({ 'consumed': True, 'message': Message('Your wounds start to feel better!', lc.green) }) return results
def attack(self, target): results = [] damage = self.power - target.fighter.defense if damage > 0: results.append({ 'message': Message( "{0} attacks {1} for {2} points of damage.".format( self.owner.name.capitalize(), target.name, str(damage)), lc.white) }) results.extend(target.fighter.take_damage(damage)) else: results.append({ 'message': Message( "{0} attacks {1} but does no damage.".format( self.owner.name.capitalize(), target.name), lc.white) }) return results
def take_turn(self,target,fov_map,game_map,entities): results=[] if self.number_of_turns>0: random_x=self.owner.x+randint(0,2)-1 random_y=self.owner.y+randint(0,2)-1 if random_x != self.owner.x and random_y != self.owner.y: self.owner.move_towards(random_x,random_y,game_map,entities) self.number_of_turns-=1 else: self.owner.ai=self.previous_ai results.append({'message':Message('The {0} is no longer confused!'.format(self.owner.name),lc.red)}) return results
def from_json(json_data): if json_data.get('use_function'): use_function = getattr(itemfunctions, json_data.get('use_function')) else: use_function = None targeting = json_data.get('targeting') if json_data.get('targeting_message'): targeting_message = Message.from_json( json_data.get('targeting_message')) else: targeting_message = None function_kwargs = json_data.get('function_kwargs') return Item(use_function, targeting, targeting_message, **function_kwargs)
def next_floor(self, player, message_log, constants): self.floor += 1 entities = [player] self.tiles = self.initialise_tiles() self.make_map(constants['max_rooms'], constants['room_min_size'], constants['room_max_size'], constants['map_width'], constants['map_height'], player, entities, constants['tile_data']) player.fighter.heal(player.fighter.max_health // 2) message_log.add_message( Message('You take a moment to rest and recover your strength.', lc.light_violet)) return entities
def drop_item(self, item): results = [] if self.owner.equipment.main_hand == item or self.owner.equipment.off_hand == item: self.owner.equipment.toggle_equip(item) item.x = self.owner.x item.y = self.owner.y self.remove_item(item) results.append({ 'item_dropped': item, 'message': Message('You dropped the {0}'.format(item.name), lc.yellow) }) return results
def play_game(player, entities, game_map, message_log, game_state, con, panel, constants): fov_recompute = True fov_map = initialise_fov(game_map) key = lc.Key() mouse = lc.Mouse() game_state = GameStates.PLAYER_TURN previous_game_state = game_state targeting_item = None while not lc.console_is_window_closed(): lc.sys_check_for_event(lc.EVENT_KEY_PRESS | lc.EVENT_MOUSE, key, mouse) if fov_recompute: recompute_fov(fov_map, player.x, player.y, constants['fov_radius'], constants['fov_light_walls'], constants['fov_algorithm']) render_all(con, panel, game_map, entities, player, fov_map, fov_recompute, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse, constants['tile_data'], game_state) fov_recompute = False lc.console_flush() action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) move = action.get('move') pickup = action.get('pickup') wait = action.get('wait') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') take_stairs = action.get('take_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_char_screen') exit = action.get('exit') fullscreen = action.get('fullscreen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] if move and game_state == GameStates.PLAYER_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if not game_map.is_blocked(destination_x, destination_y): target = get_blocking_entities_at_location( entities, destination_x, destination_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) fov_recompute = True game_state = GameStates.ENEMY_TURN elif wait: game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYER_TURN: for entity in entities: if entity.item and entity.x == player.x and entity.y == player.y: pickup_results = player.inventory.add_item(entity) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message('There is nothing here to pick up.', lc.yellow)) if show_inventory: previous_game_state = game_state game_state = GameStates.SHOW_INVENTORY if drop_inventory: previous_game_state = game_state game_state = GameStates.DROP_INVENTORY if inventory_index is not None and previous_game_state != GameStates.PLAYER_DEAD and inventory_index < len( player.inventory.items): item = player.inventory.items[inventory_index] if game_state == GameStates.SHOW_INVENTORY: player_turn_results.extend( player.inventory.use(item, entities=entities, fov_map=fov_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameStates.PLAYER_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: entities = game_map.next_floor(player, message_log, constants) fov_map = initialise_fov(game_map) fov_recompute = True lc.console_clear(con) break else: message_log.add_message( Message('There are no stairs here.', lc.yellow)) if level_up: if level_up == 'hp': player.fighter.base_max_health += 20 player.fighter.health += 20 elif level_up == 'pow': player.fighter.base_power += 1 elif level_up == 'def': player.fighter.base_defense += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, entities=entities, fov_map=fov_map, target_x=target_x, target_y=target_y) player_turn_results.extend(item_use_results) elif right_click: player_turn_results.append({'targeting_cancelled': True}) if exit: if game_state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN): game_state = previous_game_state elif game_state == GameStates.TARGETING: player_turn_results.append({'targeting_cancelled': True}) else: if not game_state == GameStates.PLAYER_DEAD: # save_game(player,entities,game_map,message_log,game_state) json_save_game(player, entities, game_map, message_log, game_state, con, constants['screen_width'], constants['screen_height'] ) #Takes about 15 times longer return True if fullscreen: lc.console_set_fullscreen(not lc.console_is_fullscreen()) for result in player_turn_results: message = result.get('message') dead_entity = result.get('dead') item_added = result.get('item_added') item_consumed = result.get('consumed') item_dropped = result.get('item_dropped') equip = result.get('equip') targeting = result.get('targeting') targeting_cancelled = result.get('targeting_cancelled') xp = result.get('xp') if message: message_log.add_message(message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled.')) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_enemy(dead_entity) message_log.add_message(message) if item_added: entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_consumed: game_state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if equip: equip_results = player.equipment.toggle_equip(equip) for result in equip_results: equipped = result.get('equipped') dequipped = result.get('dequipped') if equipped: message_log.add_message( Message('You equipped the {0}'.format( equipped.name))) if dequipped: message_log.add_message( Message('You unequipped the {0}'.format( dequipped.name))) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYER_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message('You gain {0} experience points.'.format(xp))) if leveled_up: message_log.add_message( Message( 'Your battle skills grow stronger! You reached level {0}' .format(player.level.current_level) + '!', lc.yellow)) previous_game_state = game_state game_state = GameStates.LEVEL_UP if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn( player, fov_map, game_map, entities) for result in enemy_turn_results: message = result.get('message') dead_entity = result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_enemy(dead_entity) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYER_TURN
def kill_player(player): player.char = '%' player.colour = lc.dark_red player.name = 'player\'s corpse' return Message('You died!', lc.red), GameStates.PLAYER_DEAD