def test_map(): map = libtcodpy.map_new(16, 16) assert libtcodpy.map_get_width(map) == 16 assert libtcodpy.map_get_height(map) == 16 libtcodpy.map_copy(map, map) libtcodpy.map_clear(map) libtcodpy.map_set_properties(map, 0, 0, True, True) assert libtcodpy.map_is_transparent(map, 0, 0) assert libtcodpy.map_is_walkable(map, 0, 0) libtcodpy.map_is_in_fov(map, 0, 0) libtcodpy.map_delete(map)
def draw(self): #only show if it's visible to the player; or it's set to "always visible" and on an explored tile if (libtcod.map_is_in_fov(fov_map, self.x, self.y) or (self.always_visible and map[self.x][self.y].explored)): #set the color and then draw the character that represents this object at its position libtcod.console_set_default_foreground(con, self.color) libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)
def take_turn(self): #a basic monster takes its turn. if you can see it, it can see you monster = self.owner if libtcod.map_is_in_fov(fov_map, monster.x, monster.y): #move towards player if far away if monster.distance_to(player) >= 2: monster.move_towards(player.x, player.y) #close enough, attack! (if the player is still alive.) elif player.fighter.hp > 0: monster.fighter.attack(player)
def get_names_under_mouse(): global mouse #return a string with the names of all objects under the mouse (x, y) = (mouse.cx, mouse.cy) #create a list with the names of all objects at the mouse's coordinates and in FOV names = [obj.name for obj in objects if obj.x == x and obj.y == y and libtcod.map_is_in_fov(fov_map, obj.x, obj.y)] names = ', '.join(names) #join the names, separated by commas return names.capitalize()
def closest_monster(max_range): #find closest enemy, up to a maximum range, and in the player's FOV closest_enemy = None closest_dist = max_range + 1 #start with (slightly more than) maximum range for object in objects: if object.fighter and not object == player and libtcod.map_is_in_fov(fov_map, object.x, object.y): #calculate distance between this object and the player dist = player.distance_to(object) if dist < closest_dist: #it's closer, so remember it closest_enemy = object closest_dist = dist return closest_enemy
def cast_freezeray(*args, **kwargs): entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') damage = kwargs.get('damage') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') results = [] if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message('You cannot target a tile outside your field of view.', libtcod.yellow) }) return results for entity in entities: if entity.x == target_x and entity.y == target_y and entity.ai: frozen_ai = Frozen(entity.ai, 10) frozen_ai.owner = entity entity.ai = frozen_ai entity.fighter.take_damage(damage) results.append({ 'consumed': True, 'message': Message( 'The ice bolt connects! {} is frozen!'.format( entity.name, damage), libtcod.green) }) break else: results.append({ 'consumed': False, 'message': Message('There is no targetable enemy at that location.', libtcod.yellow) }) return results
def draw_map(map_to_draw): cam_x, cam_y = globalvars.CAMERA.map_address display_map_w = constants.CAM_WIDTH // constants.CELL_WIDTH display_map_h = constants.CAM_HEIGHT // constants.CELL_HEIGHT render_w_min = cam_x - (display_map_w // 2) render_h_min = cam_y - (display_map_h // 2) render_w_max = cam_x + (display_map_w // 2) render_h_max = cam_y + (display_map_h // 2) if render_w_min < 0: render_w_min = 0 if render_h_min < 0: render_h_min = 0 if render_w_max > constants.MAP_WIDTH: render_w_max = constants.MAP_WIDTH if render_h_max > constants.MAP_HEIGHT: render_h_max = constants.MAP_HEIGHT for x in range(render_w_min, render_w_max): for y in range(render_h_min, render_h_max): tile_assignment = map_to_draw[x][y].assignment is_visible = libtcodpy.map_is_in_fov(globalvars.FOV_MAP, x, y) if is_visible: map_to_draw[x][y].explored = True if map_to_draw[x][y].block_path == True: globalvars.SURFACE_MAP.blit( globalvars.ASSETS.wall_dict[tile_assignment], (x * constants.CELL_WIDTH, y * constants.CELL_HEIGHT)) else: globalvars.SURFACE_MAP.blit( globalvars.ASSETS.S_FLOOR[0], (x * constants.CELL_WIDTH, y * constants.CELL_HEIGHT)) elif map_to_draw[x][y].explored: if map_to_draw[x][y].block_path == True: globalvars.SURFACE_MAP.blit( globalvars.ASSETS.wall_ex_dict[tile_assignment], (x * constants.CELL_WIDTH, y * constants.CELL_HEIGHT)) else: globalvars.SURFACE_MAP.blit( globalvars.ASSETS.S_FLOOREXPLORED[0], (x * constants.CELL_WIDTH, y * constants.CELL_HEIGHT))
def cast_confusion(*args, **kwargs): player = args[0] entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') turns_confused = 10 + player.fighter.magic results = [] if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message("You can't target a location outside your field of view.", libtcod.red) }) return results for entity in entities: if entity.x == target_x and entity.y == target_y and entity.ai: confused_ai = ConfusedMonster(entity.ai, turns_confused) confused_ai.owner = entity entity.ai = confused_ai results.append({ 'consumed': True, 'message': Message( "The eyes of the {0} look vacant, as it starts to stumble around! They are confused for {1} turns!" .format(entity.name, turns_confused), libtcod.light_green) }) break else: results.append({ 'consumed': False, 'message': Message("There is no targetable enemy at that location.", libtcod.red) }) return results
def cast_fireball(*args, **kwargs): """ Targeting spell - determine if damage occurs for target and apply """ entities = kwargs.get("entities") fov_map = kwargs.get("fov_map") damage = kwargs.get("damage") radius = kwargs.get("radius") target_x_pos = kwargs.get("target_x_pos") target_y_pos = kwargs.get("target_y_pos") results = [] if not tcod.map_is_in_fov(fov_map, target_x_pos, target_y_pos): results.append({ "consumed": False, "message": Message("You cannot target a tile outside your field of view.", tcod.yellow), }) return results results.append({ "consumed": True, "message": Message( f"The fireball explodes, burning everything within {radius} tiles!", tcod.orange, ), }) for entity in entities: if entity.distance(target_x_pos, target_y_pos) <= radius and entity.fighter: results.append({ "message": Message( f"The {entity.name} gets burned for {damage} hit points.", tcod.orange, ) }) results.extend(entity.fighter.take_damage(damage)) return results
def render_all(): tcod.console_set_default_foreground(con, tcod.white) tcod.console_print_ex( con, 1, SCREEN_HEIGHT - 2, tcod.BKGND_NONE, tcod.LEFT, 'HP: ' + str(player.fighter.hp) + '/' + str(player.fighter.max_hp)) global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: # recompute FOV if needed (the player moved or something) fov_recompute = False tcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) # go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = tcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: # it's out of the player's FOV if wall: tcod.console_set_char_background( con, x, y, color_dark_wall, tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, color_dark_ground, tcod.BKGND_SET) else: # it's visible if wall: tcod.console_set_char_background( con, x, y, color_light_wall, tcod.BKGND_SET) else: tcod.console_set_char_background( con, x, y, color_light_ground, tcod.BKGND_SET) # draw all objects in the list for object in objects: if object != player: object.draw() player.draw() # blit the contents of "con" to the root console tcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
def cast_fireball(*args, **kwargs): """ kwargs:\n 'entities' - all entities\n 'fov_map' - we need only those who in FOV\n 'damage' - cast damage\n 'radius' - explosion radius\n 'target_x' - target x coord 'target_y' - target y coord """ 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 libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'item_consumed': False, 'message': Message('You cannot target a tile outside view', libtcod.yellow) }) results.append({ 'item_consumed': True, 'message': Message( 'The Fireball explodes, burning everything within {0} radius!'. format(radius), libtcod.orange) }) for entity in entities: if entity.distance(target_x, target_y) <= radius and entity.fighter: results.append({ 'message': Message( 'The {0} gets burned for {1} hit points'.format( entity.name, damage), libtcod.orange) }) results.extend(entity.fighter.take_damage(damage)) return results
def cast_sleep(*args, **kwargs): player = args[0] entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') turns_asleep = 5 + player.fighter.magic results = [] if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message("You can't target a location outside your field of view.", libtcod.red) }) return results for entity in entities: if entity.x == target_x and entity.y == target_y and entity.ai: asleep_ai = AsleepMonster(entity.ai, turns_asleep) asleep_ai.owner = entity entity.ai = asleep_ai results.append({ 'consumed': True, 'message': Message( "The {0} falls asleep! They are asleep for {1} turns!". format(entity.name, turns_asleep), libtcod.light_green) }) break else: results.append({ 'consumed': False, 'message': Message("There is no targetable enemy at that location.", libtcod.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 tcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ "consumed": False, "message": Message( "You cannot target a tile outside of your field of view.", tcod.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( f"The eyes of the {entity.name} look vacant, as he starts to stumble around!", tcod.light_green, ), }) break else: results.append({ "consumed": False, "message": Message("There is no targetable enemy at that location.", tcod.yellow), }) return results
def take_turn(self, target, fov_map, game_map): results = [] monster = self.owner # Return without doing anything until it spots the player for the first time if not self.player_spotted and not libtcod.map_is_in_fov(fov_map, monster.x, monster.y): return results self.player_spotted = True self.owner.move_towards(target.x, target.y, game_map, ignore_blocking=True) if monster.distance_to(target) == 0: results.append({'message': Message("The wraith has haunted you!")}) target.status_effects.add_status(status_effects.DamageOverTime('Haunted', 5, 10)) results.extend(monster.fighter.take_damage(1)) 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 libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ "consumed": False, "message": Message( "You cannot feel the love of a tile outside your field of view(Future-octopus-vision)", libtcod.light_magenta) }) 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 {0}'s love starts to fade away, he looks like he went crazy!" .format(entity.name), libtcod.light_sepia) }) break else: results.append({ "consumed": False, "message": Message("There is no targetable enemy at that location.", libtcod.dark_crimson) }) 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 libtcod.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 lighting bolt strikes the {0} with a loud thunder! The damage is {1}' .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.', libtcod.red) }) return results
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screenWidth, screenHeight, bar_width, panel_height, panel_y, mouse, colors): #draw all tiles in the game if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = tcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: tcod.console_set_char_background(con, x, y, colors.get('light_wall'), tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, colors.get('light_ground'), tcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: tcod.console_set_char_background(con, x, y, colors.get('dark_wall'), tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, colors.get('dark_ground'), tcod.BKGND_SET) else: tcod.console_set_char_background(con, x, y, colors.get('nothing'), tcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) #draw all entities in the list for entity in entities_in_render_order: draw_entity(con, entity, fov_map) tcod.console_blit(con, 0, 0, screenWidth, screenHeight, 0, 0, 0) tcod.console_set_default_background(panel, tcod.black) tcod.console_clear(panel) y = 1 for message in message_log.messages: tcod.console_set_default_foreground(panel, message.color) tcod.console_print_ex(panel, message_log.x, y, tcod.BKGND_NONE, tcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, "HP", player.fighter.hp, player.fighter.max_hp, tcod.light_red, tcod.darker_red) tcod.console_set_default_foreground(panel, tcod.light_gray) tcod.console_print_ex(panel, 1, 0, tcod.BKGND_NONE, tcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) tcod.console_blit(panel, 0, 0, screenWidth, panel_height, 0, 0, panel_y)
def target_tile(max_range=None): #return the position of a tile left-clicked in player's FOV (optionally in a range), or (None,None) if right-clicked. global key, mouse while True: #render the screen. this erases the inventory and shows the names of objects under the mouse. libtcod.console_flush() libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS|libtcod.EVENT_MOUSE,key,mouse) render_all() (x, y) = (mouse.cx, mouse.cy) if mouse.rbutton_pressed or key.vk == libtcod.KEY_ESCAPE: return (None, None) #cancel if the player right-clicked or pressed Escape #accept the target if the player clicked in FOV, and in case a range is specified, if it's in that range if (mouse.lbutton_pressed and libtcod.map_is_in_fov(fov_map, x, y) and (max_range is None or player.distance(x, y) <= max_range)): return (x, y)
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 libtcod.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 baleful energy rips through the air and 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( 'The lightning would be useless, there are no enemies near.', libtcod.red) }) return results
def closest_enemy(self, max_range): # Find closest enemy, up to a maximum range, and in the player's FOV closest_thing = None closest_dist = max_range + 1 # Start with (slightly more than) the maximum range for object in gameMap.objects: if object.get_component( "Fighter" ) and not object == self and libtcod.map_is_in_fov( gameMap.fov_map, object.x, object.y): # Calculate distance between this object and the player dist = self.distance_to(object) if dist < closest_dist: # It's closer, so remember it closest_thing = object closest_dist = dist return closest_thing
def get_names_under_mouse(): global mouse # Return a string with the names of all the objects under the mouse (x, y) = (mouse.cx, mouse.cy) # Create a list with the names of all objects at the mouse's coordinates and in the FOV names = [ obj.name for obj in gameMap.objects if obj.x == x and obj.y == y and (libtcod.map_is_in_fov(gameMap.fov_map, obj.x, obj.y) or ignore_FOV or (obj.always_visible and gameMap.map[obj.x][obj.y].explored)) ] names = ', '.join( names) # Joins all the names together, seperated by commas return names.capitalize()
def cast_eldritch_blast_feat(*args, **kwargs): entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') damage = kwargs.get('damage') ability_power = kwargs.get('ability_power') target_x = kwargs.get('target_x') target_y = kwargs.get('target_y') results = [] if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'performed': False, 'message': Message('You cannot target a tile outside your field of view.', libtcod.yellow) }) return results for entity in entities: if entity.x == target_x and entity.y == target_y: results.append({ 'performed': True, 'message': Message( 'The {0} gets blasted for {1} hit points.'.format( entity.name, damage + (2 * ability_power)), libtcod.orange) }) results.extend( entity.fighter.take_damage(damage + (2 * ability_power))) break else: results.append({ 'performed': False, 'message': Message('There is no targetable enemy at that location.', libtcod.yellow) }) return results
def target_tile(max_range=None): global key, mouse while True: tcod.console_flush() tcod.sys_check_for_event(tcod.EVENT_KEY | tcod.EVENT_MOUSE, key, mouse) render_all() (x, y) = (mouse.cx, mouse.cy) if mouse.lbutton_pressed and tcod.map_is_in_fov( fov_map, x, y) and (max_range is None or player.distance(x, y) <= max_range): return (x, y) if mouse.rbutton_pressed or key.vk == tcod.KEY_ESCAPE: return (None, None)
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 = [] #todo change map_is_in_fov to map.Map.fov if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message('You cannot target a tile outside your field of view.', 'minor_error') }) return results for entity in entities: # Entity at location x,y with an ai and isn't a corpse if entity.x == target_x and entity.y == target_y and entity.ai and entity.render_order != RenderOrder.CORPSE: confused_ai = ai.ConfusedMonster(entity.ai, 10) confused_ai.owner = entity entity.ai = confused_ai results.append({ 'consumed': True, 'message': Message( '{0} looks confused, as they starts to stumble around!'. format(entity.full_name), 'minor_effect') }) break else: results.append({ 'consumed': False, 'message': Message('There is no enemy at that location.', 'minor_error') }) 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 libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ "consumed": False, "message": Message("You must target a tile in your line of sight.", libtcod.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 {0} is stuck by a flash of light and starts to stumble around." .format(entity.name), libtcod.lighter_purple, ), }) break else: results.append({ "consumed": False, "message": Message("There are no targetable enemies there.", libtcod.yellow), }) return results
def get_names_under_mouse(mouse, entities, fov_map): """Displays names of entities under mouse pointer. Args: mouse(Mouse): TCOD Mouse object. entities(list): List of entities to check names of. fov_map(Map): TCOD Map object used for calculating FOV. """ (x, y) = (mouse.cx, mouse.cy) names = [entity.name for entity in entities if entity.x == x and entity.y == y and libtcod.map_is_in_fov(fov_map, entity.x, entity.y)] names = ', '.join(names) return names.capitalize()
def cast_confusion(*args, **kwargs) -> list: entities = kwargs.get("entities") # Entity list fov_map = kwargs.get("fov_map") # field of view target_x = kwargs.get("target_x") # target x position target_y = kwargs.get("target_y") # Target y position results = [] if not libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ "consumed": False, "message": Message("You cannot target something you can't see.", libtcod.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( f"The eyes of the {entity.name} look vacant, as he starts to stumble around!", libtcod.light_green, ), }) break else: results.append({ "consumed": False, "message": Message("There is no targetable enemy at that location.", libtcod.yellow), }) return results
def take_turn(self, target, fov_map, game_map, entities): """ Determines if monster moves or attacks """ results = [] monster = self.owner if tcod.map_is_in_fov(fov_map, monster.x_pos, monster.y_pos): if monster.distance_to(target) >= 2: monster.move_astar(target, entities, game_map) elif target.fighter.hp > 0: attack_results = monster.fighter.attack(target) results.extend(attack_results) return results
def take_turn(self, target, fov_map, game_map, entities): results = [] monster = self.owner if libtcod.map_is_in_fov(fov_map, monster.x, monster.y): if monster.distance_to(target) >= 2: # monster.move_towards(target.x, target.y, game_map, entities) monster.move_astar(target, game_map, entities) elif target.fighter.hp > 0: attack_results = monster.fighter.attack(target) results.extend(attack_results) # If monsters don't see you they just move in a random direction else: monster.wander(game_map, entities) return results
def shoot_arrow(*args, **kwargs): caster = args[0] entities = kwargs.get('entities') fov_map = kwargs.get('fov_map') 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 libtcod.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 == None: damage = 0 else: damage = round(caster.fighter.power * (10 / (10 + target.fighter.defense))) if caster.inventory.search("Fire Arrow"): if target: results.append({'staff_used': True, 'target': target, 'message': Message("You shoot a fire arrow at the {0}! It dealt {1} damage.".format(target.name, str(damage)), libtcod.white)}) results.extend(target.fighter.take_damage(damage)) target.fighter.status = Burn(3, 3, target) print("Monster Status: " + target.fighter.status) arrow = caster.inventory.search("Fire Arrow") caster.inventory.remove_item(arrow) else: results.append({'consumed': False, 'target': None, 'message': Message("No enemy is close enough to shoot...", libtcod.orange)}) elif caster.inventory.search("Arrow"): if target: results.append({'staff_used': True, 'target': target, 'message': Message("You shoot an arrow at the {0}! It dealt {1} damage.".format(target.name, str(damage)), libtcod.white)}) results.extend(target.fighter.take_damage(damage)) arrow = caster.inventory.search("Arrow") caster.inventory.remove_item(arrow) else: results.append({'consumed': False, 'target': None, 'message': Message("No enemy is close enough to shoot...", libtcod.orange)}) else: results.append({'consumed': False, 'target': None, 'message': Message("You don't have any arrows!", libtcod.orange)}) return results
def render_all(con, panel, entities, player, game_map, fov_map, fov_recompute, message_log, screen_width, screen_height, bar_width, panel_height, panel_y, mouse, colors, game_state): # Draw all entities if fov_recompute: for y in range(game_map.height): for x in range(game_map.width): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = game_map.tiles[x][y].block_sight if visible: if wall: libtcod.console_set_char_background(con, x, y, colors.get('light_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, colors.get('light_ground'), libtcod.BKGND_SET) game_map.tiles[x][y].explored = True elif game_map.tiles[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, colors.get('dark_wall'), libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, colors.get('dark_ground'), libtcod.BKGND_SET) entities_in_render_order = sorted(entities, key=lambda x: x.render_order.value) for entity in entities_in_render_order: draw_entity(con, entity, fov_map) libtcod.console_blit(con, 0, 0, screen_width, screen_height, 0, 0, 0) libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) y = 1 for message in message_log.messages: libtcod.console_set_default_foreground(panel, libtcod.white) libtcod.console_print_ex(panel, message_log.x, y, libtcod.BKGND_NONE, libtcod.LEFT, message.text) y += 1 render_bar(panel, 1, 1, bar_width, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse(mouse, entities, fov_map)) libtcod.console_blit(panel, 0, 0, screen_width, panel_height, 0, 0, panel_y) if game_state == GameStates.SHOW_INVENTORY: inventory_menu(con, 'Press key next to item to use, or Esc to cancel\n', player.inventory, 50, screen_width, screen_height)
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 libtcod.map_is_in_fov(fov_map, target_x, target_y): results.append({ 'consumed': False, 'message': Message('You cannot target a tile outside your field of view.', libtcod.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 {0} look vacant, as he starts to stumble around!' .format(entity.name), libtcod.light_green) }) break else: results.append({ 'consumed': False, 'message': Message('There is no targetable enemy at that location.', libtcod.yellow) }) return results
def handleMessage(self, name, value): if name == 'processExplosions': self.events = {'explosions':None} explosionList = [] avatars = value['avatars'] worldMap = value['map'] items = value['items'] self.addedItems = [] for item in items + avatars: keys = item.events.keys() if item.active == True and 'explode-multi' in keys: for data in item.events['explode-multi']: [x,y] = data['coord'] foo = Entity({}) foo.x = x foo.y = y self.addExplosion({'params': data}, foo, worldMap) item.events['explode-multi'] = {} if item.active == True and 'explode' in item.events.keys(): details = item.events['explode'] if 'params' in details.keys(): self.addExplosion(details, item, worldMap) item.events['explode'] = {} for item in items + self.addedItems: if type(item).__name__ == 'Exploder' and item.active == True: affectedSpaces = [] fov_map = libtcod.map_new(worldMap.MAP_WIDTH, worldMap.MAP_HEIGHT) for y in range(item.y - item.radius, item.y + item.radius): for x in range(item.x - item.radius, item.x + item.radius): not_block_sight = not worldMap.mapArray[x][y].block_sight if (x>0 and x< worldMap.MAP_WIDTH - 1 and y > 0 and y < worldMap.MAP_HEIGHT - 1) else False not_block = not worldMap.mapArray[x][y].blocked if (x>0 and x< worldMap.MAP_WIDTH - 1 and y > 0 and y < worldMap.MAP_HEIGHT - 1) else False libtcod.map_set_properties(fov_map, x, y, not_block_sight, not_block) libtcod.map_compute_fov(fov_map, item.x, item.y, item.radius, False, 0) for y in range(item.y - item.radius, item.y + item.radius): for x in range(item.x - item.radius, item.x + item.radius): if libtcod.map_is_in_fov(fov_map, x, y): affectedSpaces.append([x, y]) worldMap.mapArray[x][y].msg('create', {'duration':item.duration, 'type':item.name, 'power':item.power, 'owner':item.pwner, 'maxSpreads':item.maxSpreads, 'original':id(item)}) explosionList.append({'originator':item, 'name':item.name, 'affectedSpaces':affectedSpaces}) item.active = False self.events = {'explosions':explosionList}
def take_turn(self, target, fov_map, game_map, entities): results = [] monster = self.owner if libtcod.map_is_in_fov(fov_map, monster.x, monster.y): if monster.distance_to(target) >= 2: monster.move_astar(target=target, entities=entities, game_map=game_map) elif target.party.members and monster.party.random_member_no_cooldown( ): attack_results = monster.party.random_member_no_cooldown( ).attack(target=target) results.extend(attack_results) return results
def cast_weaken(*args, **kwargs): caster = args[0] entities = kwargs.get('entities') damage = kwargs.get('amount') maximum_range = kwargs.get('maximum_range') fov_map = kwargs.get('fov_map') results = [] target = None closest_distance = maximum_range + 1 for entity in entities: if entity.combat_entity and entity != caster and tcod.map_is_in_fov( fov_map, entity.x, entity.y) and entity.combat_entity.hp > 0: distance = caster.distance_to_target(entity) if distance < closest_distance: target = entity closest_distance = distance if target: damage = damage - target.combat_entity.defense results.append({ 'spell_success': True, 'target': target, 'message': Message( 'You drain the {0} of part of its power!'.format(target.name), tcod.pink) }) results.extend(target.combat_entity.update_power(damage * (-1))) else: results.append({ 'spell_success': False, 'target': None, 'message': Message('There is no enemy close enough for this spell.', tcod.pink) }) return results
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) #go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #if it's not visible right now, the player can only see it if it's explored if map[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET ) else: libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET ) #since it's visible, explore it map[x][y].explored = True #draw all objects in the list, except the player. we want it to #always appear over all other objects! so it's drawn later. for object in objects: if object != player: object.draw() player.draw() #blit the contents of "con" to the root console libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0) #show the player's stats libtcod.console_set_default_foreground(con, libtcod.white) libtcod.console_print_ex(0, 1, SCREEN_HEIGHT - 2, libtcod.BKGND_NONE, libtcod.LEFT, 'HP: ' + str(player.fighter.hp) + '/' + str(player.fighter.max_hp))
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) #go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #if it's not visible right now, the player can only see it if it's explored if map[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET ) else: libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET ) #since it's visible, explore it map[x][y].explored = True #draw all objects in the list for object in objects: object.draw() #blit the contents of "con" to the root console libtcod.console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0)
def draw(self): #only show if it's visible to the player if libtcod.map_is_in_fov(fov_map, self.x, self.y): #set the color and then draw the character that represents this object at its position libtcod.console_set_default_foreground(con, self.color) libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)
def is_visible(self, x, y): return T.map_is_in_fov(self.fov_map, x, y) and \ distance(x, y, self.player.x, self.player.y) <= \ self.player.fov_range
def render_all(): global fov_map, color_dark_wall, color_light_wall global color_dark_ground, color_light_ground global fov_recompute if fov_recompute: #recompute FOV if needed (the player moved or something) fov_recompute = False libtcod.map_compute_fov(fov_map, player.x, player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO) #go through all tiles, and set their background color according to the FOV for y in range(MAP_HEIGHT): for x in range(MAP_WIDTH): visible = libtcod.map_is_in_fov(fov_map, x, y) wall = map[x][y].block_sight if not visible: #if it's not visible right now, the player can only see it if it's explored if map[x][y].explored: if wall: libtcod.console_set_char_background(con, x, y, color_dark_wall, libtcod.BKGND_SET) else: libtcod.console_set_char_background(con, x, y, color_dark_ground, libtcod.BKGND_SET) else: #it's visible if wall: libtcod.console_set_char_background(con, x, y, color_light_wall, libtcod.BKGND_SET ) else: libtcod.console_set_char_background(con, x, y, color_light_ground, libtcod.BKGND_SET ) #since it's visible, explore it map[x][y].explored = True #draw all objects in the list, except the player. we want it to #always appear over all other objects! so it's drawn later. for object in objects: if object != player: object.draw() player.draw() #blit the contents of "con" to the root console libtcod.console_blit(con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0, 0) #prepare to render the GUI panel libtcod.console_set_default_background(panel, libtcod.black) libtcod.console_clear(panel) #print the game messages, one line at a time y = 1 for (line, color) in game_msgs: libtcod.console_set_default_foreground(panel, color) libtcod.console_print_ex(panel, MSG_X, y, libtcod.BKGND_NONE, libtcod.LEFT, line) y += 1 #show the player's stats render_bar(1, 1, BAR_WIDTH, 'HP', player.fighter.hp, player.fighter.max_hp, libtcod.light_red, libtcod.darker_red) #display names of objects under the mouse libtcod.console_set_default_foreground(panel, libtcod.light_gray) libtcod.console_print_ex(panel, 1, 0, libtcod.BKGND_NONE, libtcod.LEFT, get_names_under_mouse()) #blit the contents of "panel" to the root console libtcod.console_blit(panel, 0, 0, SCREEN_WIDTH, PANEL_HEIGHT, 0, 0, PANEL_Y)