def play_game(player, entities, game_map, message_log, game_state, root_console, con, panel, constants): tdl.set_font('arial10x10.png', greyscale=True, altLayout=True) fov_recompute = True mouse_coordinates = (0, 0) previous_game_state = game_state targeting_item = None while not tdl.event.is_window_closed(): if fov_recompute: game_map.compute_fov(player.x, player.y, fov=constants['fov_algorithm'], radius=constants['fov_radius'], light_walls=constants['fov_light_walls']) render_all(con, panel, entities, player, game_map, fov_recompute, root_console, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse_coordinates, constants['colors'], game_state) tdl.flush() clear_all(con, entities) fov_recompute = False for event in tdl.event.get(): if event.type == 'KEYDOWN': user_input = event break elif event.type == 'MOUSEMOTION': mouse_coordinates = event.cell elif event.type == 'MOUSEDOWN': user_mouse_input = event break else: user_input = None user_mouse_input = None if not (user_input or user_mouse_input): continue action = handle_keys(user_input, game_state) mouse_action = handle_mouse(user_mouse_input) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') 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_character_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.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if game_map.walkable[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.PLAYERS_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, constants['colors']) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message('There is nothing here to pick up.', constants['colors'].get('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, constants['colors'], entities=entities, game_map=game_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend( player.inventory.drop_item(item, constants['colors'])) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: game_map, entities = next_floor(player, message_log, entity.stairs.floor, constants) fov_recompute = True con.clear() break else: message_log.add_message( Message('There are no stairs here.', constants['colors'].get('yellow'))) if level_up: if level_up == 'hp': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': 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, constants['colors'], entities=entities, game_map=game_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: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: tdl.set_fullscreen(not tdl.get_fullscreen()) for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_result.get('xp') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity, constants['colors']) else: message = kill_monster(dead_entity, constants['colors']) 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 equip_result in equip_results: equipped = equip_result.get('equipped') dequipped = equip_result.get('dequipped') if equipped: message_log.add_message( Message(f'You equipped the {equipped.name}')) if dequipped: message_log.add_message( Message(f'You dequipped the {dequipped.name}')) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message('Targeting cancelled')) 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) + '!', constants['colors'].get('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, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player( dead_entity, constants['colors']) else: message = kill_monster(dead_entity, constants['colors']) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYERS_TURN
def play_game(player, entities, game_map, message_log, game_state, con, panel): fov_recompute = True mouse_coordinates = (0, 0) key = libtcod.Key() mouse = libtcod.Mouse() previous_game_state = game_state targeting_item = None while not libtcod.console_is_window_closed(): libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) if fov_recompute: game_map.compute_fov(player.x, player.y, fov=constants.fov_algorithm, radius=constants.fov_radius, light_walls=constants.fov_light_walls) render_all(con, panel, entities, player, game_map, fov_recompute, message_log, mouse_coordinates, game_state) libtcod.console_flush() clear_all(con, entities) fov_recompute = False action = handle_keys(key, game_state) mouse_action = handle_mouse(mouse) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') 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_character_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.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if game_map.walkable[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 and game_state == GameStates.PLAYERS_TURN: game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYERS_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', colors.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 # Player is manipulating 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, game_map=game_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend(player.inventory.drop_item(item)) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: game_map, entities = next_floor(player, message_log, entity.stairs.floor) fov_recompute = True con.clear() break else: message_log.add_message(Message('There are no stairs here', colors.yellow)) if level_up: if level_up == 'hp': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': 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, game_map=game_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: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: libtcod.console_set_fullscreen(not libtcod.console_is_fullscreen()) for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_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 xp: leveled_up = player.level.add_xp(xp) message_log.add_message(Message(f'You gain {xp} experience points')) if leveled_up: message_log.add_message(Message( f'Your battle skills grow stronger! You reached level {player.level.current_level}!', colors.yellow )) previous_game_state = game_state game_state = GameStates.LEVEL_UP if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity) else: message = kill_monster(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 equip_result in equip_results: equipped = equip_result.get('equipped') dequipped = equip_result.get('dequipped') if equipped: message_log.add_message(Message(f'You equipped the {equipped.name}')) if dequipped: message_log.add_message(Message(f'You dequipped the {dequipped.name}')) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting # noinspection PyUnresolvedReferences message_log.add_message(targeting_item.item.targeting_message) if game_state == GameStates.ENEMY_TURN: for entity in entities: if entity.ai: enemy_turn_results = entity.ai.take_turn(player, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_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_monster(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.PLAYERS_TURN
def play(player, entities, game_map, display, state): mouse_coordinates = (0, 0) prev_state = state targeting_item = None while not tdl.event.is_window_closed(): game_map.player_FOV() display.render_all(mouse_coordinates, state, targeting_item) tdl.flush() display.clear_all() for event in tdl.event.get(): if event.type == 'KEYDOWN': user_input = event break elif event.type == 'MOUSEMOTION': mouse_coordinates = event.cell elif event.type == 'MOUSEDOWN': user_mouse_input = event break else: user_input = None user_mouse_input = None if not (user_input or user_mouse_input): continue action = handle_keys(user_input, state) mouse_action = handle_mouse(user_mouse_input) move = action.get('move') exit = action.get('exit') pickup = action.get('pickup') wait = action.get('wait') inventory = action.get('inventory') drop = action.get('drop') shop = action.get('shop') buy = action.get('buy') sell = action.get('sell') sell_index = action.get('vendor_sell_index') buy_index = action.get('vendor_buy_index') inventory_index = action.get('inventory_index') go_down = action.get('go_down') level_up = action.get('level_up') character_screen = action.get('character_screen') fullscreen = action.get('fullscreen') direction_selected = action.get('direction_selected') controls_screen = action.get('controls_screen') left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] if exit: if state in (GameStates.VENDOR_BUY, GameStates.VENDOR_SELL): state = prev_state prev_state = GameStates.PLAYER_TURN elif state in (GameStates.SHOW_INVENTORY, GameStates.DROP_INVENTORY, GameStates.CHARACTER_SCREEN, GameStates.VENDOR_SELECT, GameStates.SHOW_CONTROLS): state = prev_state elif state in (GameStates.TARGETING, GameStates.DIRECTIONAL_TARGETING): player_turn_results.append({'targeting_cancelled': True}) else: save_game(player, entities, game_map, display.log, state) return True if move and state == GameStates.PLAYER_TURN: dx, dy = move dest_x = player.x + dx dest_y = player.y + dy if game_map.walkable[dest_x, dest_y]: if len(player.inventory.items) <= player.inventory.capacity: target = get_impassable_entities_at(entities, dest_x, dest_y) if target: attack_results = player.fighter.attack(target) player_turn_results.extend(attack_results) else: player.move(dx, dy) state = GameStates.ENEMY_TURN else: display.write(Message('You are overburdened and cannot move!', Colors.YELLOW)) elif pickup and 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(entity) player_turn_results.extend(pickup_results) break else: display.write(Message('There is nothing here to pick up', Colors.YELLOW)) if wait and state == GameStates.PLAYER_TURN: state = GameStates.ENEMY_TURN if inventory: prev_state = state state = GameStates.SHOW_INVENTORY if buy: prev_state = state state = GameStates.VENDOR_SELL if sell: prev_state = state state = GameStates.VENDOR_BUY if character_screen: prev_state = state state = GameStates.CHARACTER_SCREEN if controls_screen: prev_state = state state = GameStates.SHOW_CONTROLS if drop: prev_state = state state = GameStates.DROP_INVENTORY if inventory_index is not None and prev_state != GameStates.PLAYER_DEAD and inventory_index < len(player.inventory.items): item = player.inventory.items[inventory_index] if state == GameStates.SHOW_INVENTORY: player_turn_results.extend(player.inventory.use( item, game_map=game_map, source=player)) else: player_turn_results.extend(player.inventory.drop(item)) if buy_index is not None and prev_state != GameStates.PLAYER_DEAD and buy_index < len(player.inventory.items): item = player.inventory.get_and_remove(buy_index) vendor = None for entity in entities: if entity.vendor and entity.x == player.x and entity.y == player.y: vendor = entity if vendor: vendor.vendor.purchase(item) player.inventory.cashola += item.item.price if sell_index is not None: vendor = None item = None for entity in entities: if entity.vendor and entity.x == player.x and entity.y == player.y: vendor = entity if vendor: price = vendor.vendor.get_price(sell_index) if price is None: display.write(Message('I\'m afraid I don\'t have that listing.', Colors.YELLOW)) elif player.inventory.cashola < price: display.write(Message('I\'m afraid you can\'t afford that item.', Colors.YELLOW)) else: item = vendor.vendor.sell(sell_index) if item: player.inventory.silent_add(item) player.inventory.cashola -= item.item.price if go_down and state == GameStates.PLAYER_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: game_map, entities = next_floor(player, display, entity.stairs.target_floor) break else: display.write(Message('There are no stairs here.', Colors.YELLOW)) if shop and state == GameStates.PLAYER_TURN: for entity in entities: if entity.vendor and entity.x == player.x and entity.y == player.y: prev_state = state state = GameStates.VENDOR_SELECT break else: display.write(Message('There are no vendors here.', Colors.YELLOW)) if state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use( targeting_item, game_map=game_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 state == GameStates.DIRECTIONAL_TARGETING: if direction_selected: item_use_results = player.inventory.use( targeting_item, game_map=game_map, direction=direction_selected) player_turn_results.extend(item_use_results) if level_up: if level_up == 'constitution': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'strength': player.fighter.base_power += 1 elif level_up == 'agility': player.fighter.base_defense += 1 elif level_up == 'dexterity': player.fighter.base_accuracy += 2 elif level_up == 'endurance': if player.inventory.base_capacity > 23: display.write(Message('You cannot advance endurance further!', Colors.YELLOW)) continue player.inventory.base_capacity += 3 state = prev_state if fullscreen: tdl.set_fullscreen(not tdl.get_fullscreen()) for player_result in player_turn_results: player_message = player_result.get('message') dead_entity_PT = player_result.get('dead') item_added = player_result.get('item_added') item_consumed = player_result.get('consumed') item_dropped = player_result.get('item_dropped') equip = player_result.get('equip') charge_used = player_result.get('charge_used') targeting = player_result.get('targeting') directional_targeting = player_result.get('directional_targeting') targeting_cancelled = player_result.get('targeting_cancelled') xp = player_result.get('xp') if player_message: display.write(player_message) if dead_entity_PT: if dead_entity_PT == player: player_message, state = kill_player(dead_entity_PT) else: player_message = kill_monster(dead_entity_PT, game_map) display.write(player_message) if item_added: entities.remove(item_added) state = GameStates.ENEMY_TURN if item_consumed: state = GameStates.ENEMY_TURN if item_dropped: entities.append(item_dropped) state = GameStates.ENEMY_TURN if charge_used: state = GameStates.ENEMY_TURN if targeting_cancelled: state = GameStates.PLAYER_TURN display.write(Message('Targeting cancelled')) if equip: equip_results = player.equipment.toggle_equip(equip) for equip_result in equip_results: equipped = equip_result.get('equipped') removed = equip_result.get('removed') if equipped: display.write(Message('You equip the {0}'.format(equipped.name))) if removed: display.write(Message('You remove the {0}'.format(removed.name))) state = GameStates.ENEMY_TURN if xp: leveled_up = player.level.add_xp(xp) if leveled_up: display.write(Message('Welcome to level {0}!'.format( player.level.current_level), Colors.LIGHT_RED)) prev_state = state state = GameStates.LEVEL_UP # canceling from targeting will return to PLAYER mode, not INVENTORY if targeting: prev_state = GameStates.PLAYER_TURN state = GameStates.TARGETING targeting_item = targeting display.write(targeting_item.item.targeting_msg) if directional_targeting: prev_state = GameStates.PLAYER_TURN state = GameStates.DIRECTIONAL_TARGETING targeting_item = directional_targeting display.write(targeting_item.item.targeting_msg) sanity_check(player) if state == GameStates.ENEMY_TURN: game_map.enemy_FOV() for entity in entities: if entity.regeneration: entity.regeneration.regen() if entity.ai: enemy_turn_results = entity.ai.take_turn(player, game_map) for enemy_result in enemy_turn_results: enemy_message = enemy_result.get('message') dead_entity_ET = enemy_result.get('dead') if enemy_message: display.write(enemy_message) if dead_entity_ET: if dead_entity_ET == player: enemy_message, state = kill_player(dead_entity_ET) else: enemy_message = kill_monster(dead_entity_ET, game_map) display.write(enemy_message) if state == GameStates.PLAYER_DEAD: break if state == GameStates.PLAYER_DEAD: break else: state = GameStates.PLAYER_TURN
def play_game(player, entities, game_map, message_log, game_state, root_console, con, panel, constants): tdl.set_font("arial10x10.png", greyscale=True, altLayout=True) fov_recompute = True mouse_coordinates = (0, 0) previous_game_state = game_state targeting_item = None while not tdl.event.is_window_closed(): if fov_recompute: game_map.compute_fov(player.x, player.y, fov=constants["fov_algorithm"], radius=constants["fov_radius"], light_walls=constants["fov_light_walls"]) render_all(con, panel, entities, player, game_map, fov_recompute, root_console, message_log, constants["screen_width"], constants["screen_height"], constants["bar_width"], constants["panel_height"], constants["panel_y"], mouse_coordinates, constants["colors"], game_state) tdl.flush() clear_all(con, entities) fov_recompute = False for event in tdl.event.get(): if event.type == "KEYDOWN": user_input = event break elif event.type == "MOUSEMOTION": mouse_coordinates = event.cell elif event.type == "MOUSEDOWN": user_mouse_input = event break else: user_input = None user_mouse_input = None if not (user_input or user_mouse_input): continue action = handle_keys(user_input, game_state) mouse_action = handle_mouse(user_mouse_input) move = action.get("move") wait = action.get("wait") pickup = action.get("pickup") 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_character_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.PLAYERS_TURN: dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if game_map.walkable[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.PLAYERS_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, constants["colors"]) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message("Nothing to pick up.", constants["colors"].get("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, constants["colors"], entities=entities, game_map=game_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend( player.inventory.drop_item(item, constants["colors"])) if take_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: game_map, entities = next_floor(player, message_log, entity.stairs.floor, constants) fov_recompute = True con.clear() break else: message_log.add_message( Message("There are no stairs here.", constants["colors"].get("yellow"))) if level_up: if level_up == "hp": player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == "str": 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, constants["colors"], entities=entities, game_map=game_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: save_game(player, entities, game_map, message_log, game_state) return True if fullscreen: tdl.set_fullscreen(not tdl.get_fullscreen()) for player_turn_result in player_turn_results: message = player_turn_result.get("message") dead_entity = player_turn_result.get("dead") item_added = player_turn_result.get("item_added") item_consumed = player_turn_result.get("consumed") item_dropped = player_turn_result.get("item_dropped") equip = player_turn_result.get("equip") targeting = player_turn_result.get("targeting") targeting_cancelled = player_turn_result.get("targeting_cancelled") xp = player_turn_result.get("xp") if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player(dead_entity, constants["colors"]) else: message = kill_monster(dead_entity, constants["colors"]) 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 equip_result in equip_results: equipped = equip_result.get("equipped") dequipped = equip_result.get("dequipped") if equipped: message_log.add_message( Message("Equipped {0}.".format(equipped.name))) if dequipped: message_log.add_message( Message("Removed {0}.".format(dequipped.name))) game_state = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if targeting_cancelled: game_state = previous_game_state message_log.add_message(Message("Targeting cancelled.")) if xp: leveled_up = player.level.add_xp(xp) message_log.add_message( Message("{0} experience gained.".format(xp))) if leveled_up: #todo take another shot at the level up message message_log.add_message( Message( "Your effort pays off, and you reach level {0}!". format(player.level.current_level), constants["colors"].get("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, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get("message") dead_entity = enemy_turn_result.get("dead") if message: message_log.add_message(message) if dead_entity: if dead_entity == player: message, game_state = kill_player( dead_entity, constants["colors"]) else: message = kill_monster(dead_entity, constants["colors"]) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: game_state = GameStates.PLAYERS_TURN
def play_game(player, entities, game_map, message_log, game_state, root_console, con, panel, lexicon, constants): tdl.set_font('resources/arial10x10.png', greyscale=True, altLayout=True) fov_recompute = True fov_radius = 2 if player.body.l_eye.state.name != 'LOST': fov_radius += 9 if player.body.r_eye.state.name != 'LOST': fov_radius += 9 mouse_coordinates = (0, 0) previous_game_state = game_state #game_state = GameStates.HELP_SCREEN targeting_item = None invisible_turns = 0 verse = '' reading_scroll = None message_log.add_message(Message("Press '?' for Help Screen")) #uncomment the next line to facilitate manual testing of new spells print(lexicon) while not tdl.event.is_window_closed(): if fov_recompute: fov_radius = 2 if player.body.l_eye.state.name != 'LOST': fov_radius += 4 if player.body.r_eye.state.name != 'LOST': fov_radius += 4 game_map.compute_fov(player.x, player.y, fov=constants['fov_algorithm'], radius=fov_radius, light_walls=constants['fov_light_walls']) render_all(con, panel, entities, player, game_map, fov_recompute, root_console, message_log, constants['screen_width'], constants['screen_height'], constants['bar_width'], constants['panel_height'], constants['panel_y'], mouse_coordinates, constants['colors'], game_state, reading_scroll) tdl.flush() clear_all(con, entities) fov_recompute = False for event in tdl.event.get(): if event.type == 'KEYDOWN': user_input = event break elif event.type == 'MOUSEMOTION': mouse_coordinates = event.cell elif event.type == 'MOUSEDOWN': user_mouse_input = event break else: user_input = None user_mouse_input = None if not (user_input or user_mouse_input): continue action = handle_keys(user_input, game_state) mouse_action = handle_mouse(user_mouse_input) move = action.get('move') wait = action.get('wait') pickup = action.get('pickup') show_inventory = action.get('show_inventory') drop_inventory = action.get('drop_inventory') inventory_index = action.get('inventory_index') take_down_stairs = action.get('take_down_stairs') take_up_stairs = action.get('take_up_stairs') level_up = action.get('level_up') show_character_screen = action.get('show_character_screen') show_body_screen = action.get('show_body_screen') show_help_screen = action.get('show_help_screen') look_around = action.get('look_around') cast_spell = action.get('cast_spell') letter = action.get('letter') exit = action.get('exit') fullscreen = action.get('fullscreen') make_visible = False left_click = mouse_action.get('left_click') right_click = mouse_action.get('right_click') player_turn_results = [] if move and game_state == GameStates.PLAYERS_TURN: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True dx, dy = move destination_x = player.x + dx destination_y = player.y + dy if game_map.walkable[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) if not player.fighter.visible: player.fighter.make_visible() message_log.add_message( Message('You are visible again!')) else: player.move(dx, dy) fov_recompute = True game_state = GameStates.ENEMY_TURN elif wait and game_state == GameStates.PLAYERS_TURN: player.body.pump_blood() for entity in entities: if entity.fountain and entity.x == player.x and entity.y == player.y: if entity.fountain.water: entity.fountain.drink(player) message_log.add_message( Message('You drink and feel refreshed.', constants['colors'].get('blue'))) else: message_log.add_message( Message('The fountain is dry.', constants['colors'].get('yellow'))) game_state = GameStates.ENEMY_TURN elif pickup and game_state == GameStates.PLAYERS_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, constants['colors']) player_turn_results.extend(pickup_results) break else: message_log.add_message( Message('There is nothing here to pick up.', constants['colors'].get('yellow'))) if show_inventory and game_state != GameStates.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: if item.name.split()[0] == 'Scroll': game_state = GameStates.READ_SCROLL reading_scroll = item else: player_turn_results.extend( player.inventory.use(item, constants['colors'], entities=entities, game_map=game_map)) elif game_state == GameStates.DROP_INVENTORY: player_turn_results.extend( player.inventory.drop_item(item, constants['colors'])) if look_around: if game_state != GameStates.UNDERWORLD: seen = ', '.join([ entity.name for entity in entities if game_map.fov[entity.x, entity.y] and entity is not player and not entity.ghost ]) message_log.add_message( Message('You see: {0}.'.format(seen), constants['colors'].get('white'))) else: seen = ', '.join([ entity.name for entity in entities if game_map.fov[entity.x, entity.y] and entity is not player and entity.ghost ]) message_log.add_message( Message('You see: {0}.'.format(seen), constants['colors'].get('white'))) if cast_spell: message_log.add_message( Message('You begin a magic spell incantation.', constants['colors'].get('white'))) previous_game_state = game_state game_state = GameStates.CASTING_SPELL if letter: if letter == '.': magic_verse = [] for i in verse.split(): if player.caster.mana > 0 and player.caster.focus > 0: player.caster.mana -= 1 player.caster.focus -= 1 magic_verse.append(i) verse = ' '.join(translate(magic_verse, lexicon)) message_log.add_message( Message(verse, constants['colors'].get('white'))) spell_results = player.caster.cast_spell( verse.split(), game_map, entities, constants['colors']) verse = '' player_turn_results.extend(spell_results) else: verse += letter if take_down_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: if entity.stairs.direction == 'down': save_floor(player, entities, game_map) game_map, entities = next_floor( player, message_log, entity.stairs.floor, constants, lexicon, 'down') fov_recompute = True con.clear() break else: message_log.add_message( Message('These are not down stairs.', constants['colors'].get('yellow'))) break else: message_log.add_message( Message('There are no stairs here.', constants['colors'].get('yellow'))) if take_up_stairs and game_state == GameStates.PLAYERS_TURN: for entity in entities: if entity.stairs and entity.x == player.x and entity.y == player.y: if entity.stairs.direction == 'up': save_floor(player, entities, game_map) game_map, entities = next_floor( player, message_log, entity.stairs.floor, constants, lexicon, 'up') fov_recompute = True con.clear() break else: message_log.add_message( Message('These are not up stairs.', constants['colors'].get('yellow'))) break else: message_log.add_message( Message('There are no stairs here.', constants['colors'].get('yellow'))) if level_up: if level_up == 'hp': player.fighter.base_max_hp += 20 player.fighter.hp += 20 elif level_up == 'str': player.fighter.base_power += 2 elif level_up == 'def': player.fighter.base_defense += 1 elif level_up == 'mp': player.caster.base_max_mana += 2 player.caster.mana += 2 elif level_up == 'fcs': player.caster.base_max_focus += 1 player.caster.focus += 1 game_state = previous_game_state if show_character_screen: previous_game_state = game_state game_state = GameStates.CHARACTER_SCREEN if show_body_screen: previous_game_state = game_state game_state = GameStates.BODY_SCREEN if show_help_screen: previous_game_state = game_state game_state = GameStates.HELP_SCREEN if game_state == GameStates.TARGETING: if left_click: target_x, target_y = left_click item_use_results = player.inventory.use(targeting_item, constants['colors'], entities=entities, game_map=game_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, GameStates.HELP_SCREEN, GameStates.BODY_SCREEN): game_state = previous_game_state elif game_state == GameStates.TARGETING: player_turn_results.append({'targeting_cancelled': True}) elif game_state == GameStates.READ_SCROLL: game_state = GameStates.PLAYERS_TURN else: save_game(player, entities, game_map, message_log, game_state, lexicon) return True if fullscreen: tdl.set_fullscreen(not tdl.get_fullscreen()) if make_visible: player.fighter.make_visible() make_visible = False message_log.add_message(Message('You are visible again!')) game_state = GameStates.ENEMY_TURN for player_turn_result in player_turn_results: message = player_turn_result.get('message') dead_entity = player_turn_result.get('dead') item_added = player_turn_result.get('item_added') item_consumed = player_turn_result.get('consumed') item_dropped = player_turn_result.get('item_dropped') equip = player_turn_result.get('equip') targeting = player_turn_result.get('targeting') targeting_cancelled = player_turn_result.get('targeting_cancelled') xp = player_turn_result.get('xp') magic_xp = player_turn_result.get('magic_xp') invisible = player_turn_result.get('invisible') spell_cast = player_turn_result.get('spell_cast') spell_failed = player_turn_result.get('spell_failed') if invisible: invisible_turns = player_turn_result.get('invisible_turns') game_state = GameStates.ENEMY_TURN if make_visible: player.fighter.make_visible() make_visible = False message_log.add_message(Message('You are visible again!')) game_state = GameStates.ENEMY_TURN 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, constants['colors']) else: message = kill_monster(dead_entity, entities, constants['colors']) message_log.add_message(message) if item_added: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True entities.remove(item_added) game_state = GameStates.ENEMY_TURN if item_consumed: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True game_state = GameStates.ENEMY_TURN if item_dropped: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True entities.append(item_dropped) game_state = GameStates.ENEMY_TURN if spell_cast: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True game_state = GameStates.ENEMY_TURN if spell_failed: if not player.fighter.visible: invisible_turns -= 1 if invisible_turns <= 0: make_visible = True game_state = GameStates.ENEMY_TURN if equip: equip_results = player.equipment.toggle_equip(equip) for equip_result in equip_results: equipped = equip_result.get('equipped') dequipped = equip_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 dequipped the {0}'.format( dequipped.name))) game_stat = GameStates.ENEMY_TURN if targeting: previous_game_state = GameStates.PLAYERS_TURN game_state = GameStates.TARGETING targeting_item = targeting message_log.add_message(targeting_item.item.targeting_message) if xp: leveled_up = player.level.add_fighter_xp(xp) message_log.add_message( Message('You gain {0} experience points.'.format(xp))) if leveled_up: message_log.add_message( Message( 'Your fighting skills improve! You reach combat level {0}' .format(player.level.fighter_level) + '!', constants['colors'].get('yellow'))) previous_game_state = game_state game_state = GameStates.LEVEL_UP if magic_xp: magic_leveled_up = player.level.add_caster_xp(magic_xp) message_log.add_message( Message('You gain {0} magic experience points.'.format( magic_xp))) if magic_leveled_up: message_log.add_message( Message( 'Your casting skills improve! You reach magic level {0}' .format(player.level.caster_level) + '!', constants['colors'].get('yellow'))) previous_game_state = game_state game_state = GameStates.MAGIC_LEVEL_UP if game_state == GameStates.ENEMY_TURN: if player.caster.focus < player.caster.max_focus: player.caster.focus += player.caster.regeneration for entity in entities: if entity.body and entity.body.alive: body_turn_results = entity.body.take_turn() for result in body_turn_results: dead_entity = result.get('dead') message = result.get('message') if dead_entity: if dead_entity == player: message, game_state = kill_player( dead_entity, constants['colors']) else: message = kill_monster(dead_entity, entities, constants['colors']) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if message: message_log.add_message(message) if entity.ai and entity.body.animated: enemy_turn_results = entity.ai.take_turn( player, game_map, entities) for enemy_turn_result in enemy_turn_results: message = enemy_turn_result.get('message') dead_entity = enemy_turn_result.get('dead') xp = enemy_turn_result.get('xp') if message: message_log.add_message(message) if xp: leveled_up = player.level.add_fighter_xp(xp) if leveled_up: message_log.add_message( Message( 'Your fighting skills improve! You reach combat level {0}' .format(player.level.fighter_level) + '!', constants['colors'].get('yellow'))) previous_game_state = game_state game_state = GameStates.LEVEL_UP if dead_entity: if dead_entity == player: message, game_state = kill_player( dead_entity, constants['colors']) else: message = kill_monster(dead_entity, entities, constants['colors']) message_log.add_message(message) if game_state == GameStates.PLAYER_DEAD: break if game_state == GameStates.PLAYER_DEAD: break else: if game_state == GameStates.LEVEL_UP: previous_game_state = GameStates.PLAYERS_TURN else: game_state = GameStates.PLAYERS_TURN