def path_from_to(self, pos_origin, pos_destination): # For the moment, we do not handle Z movement x, y, z = pos_origin x2, y2, _ = pos_destination path = tcod.path_new_using_map(self.path_map[z]) tcod.path_compute(path, x, y, x2, y2) return path
def move_astar(self, target): fov = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) #set move, sight blockers for y1 in range(MAP_HEIGHT): for x1 in range(MAP_WIDTH): libtcod.map_set_properties(fov, x1, y1, not map[x1][y1].sight_blocker, not map[x1][y1].move_blocker) #Treat tiles occupied by monsters as move blocked for obj in objects: if obj.move_blocker and obj != self and obj != target: libtcod.map_set_properties(fov, obj.x, obj.y, True, False) #Allocate path. Use roguelike geometry (diagonals = cardinals). my_path = libtcod.path_new_using_map(fov, 1.0) #Compute path libtcod.path_compute(my_path, self.x, self.y, target.x, target.y) #Confirm path was found, and is short, then take step. if not libtcod.path_is_empty(my_path) and libtcod.path_size(my_path) < MAX_ASTAR_PATH_LENGTH: x, y = libtcod.path_walk(my_path, True) if x or y: #self.move takes dx, dy so don't use that self.x = x self.y = y #If the path is bad, take direct path to player. #This happens if, say, player is behind a monster in a corridor. else: self.move_towards(target.x, target.y) #Deallocate path memory libtcod.path_delete(my_path)
def move_towards(gamemap_instance, thisobject, target_x, target_y): """ Move towards a target_x, target_y coordinate. This method computes the A* path and uses move() to actually implement the movement. """ fov_map = gamemap_instance.fov_map path = libtcod.path_new_using_map(fov_map) libtcod.path_compute(path, thisobject.x, thisobject.y, target_x, target_y) pathx, pathy = libtcod.path_walk(path, True) # If the monster tries to move toward something, such as the player, which is standing # inside of a wall or other blocked spot, path_walk will return None but the dx and dy # calculations will crap out because you can't mix int and NoneType. if pathx is None or pathy is None: return dx = pathx - thisobject.x dy = pathy - thisobject.y distance = sqrt(dx ** 2 + dy ** 2) #normalize it to length 1 (preserving direction), then round it and #convert to integer so the movement is restricted to the map grid dx = int(round(dx / distance)) dy = int(round(dy / distance)) move(gamemap_instance, thisobject, dx, dy)
def create_path(self, gamemap_instance): mymap = gamemap_instance.level #Create the path map self.path_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) for x in range(1, MAP_WIDTH): for y in range(1, MAP_HEIGHT): libtcod.map_set_properties(self.path_map, x, y, not mymap[x][y].block_sight, not mymap[x][y].blocked) print 'Builder created self.path_map' self.is_pathmap_created = True # now use the path map to create the path from the explorer's current position to another spot: self.path = libtcod.path_new_using_map(self.path_map) destinationx, destinationy = self.pick_spot_to_work(gamemap_instance) if destinationx is not None: self.work_target = (destinationx, destinationy) print 'Builder chose a work target at ' + str(self.work_target[0]) +', ' + str(self.work_target[1]) + '.' libtcod.path_compute(self.path, self.owner.x, self.owner.y, destinationx, destinationy) #originx, originy = libtcod.path_get_origin(self.path) #destx, desty = libtcod.path_get_destination(self.path) elif destinationx is None: print 'destinationx is None.'
def missile_attack(sx, sy, dx, dy, trap=False): cx, cy = sx, sy if sx == dx: char = '|' if sy == dy: char = chr(196) if (sx < dx and sy > dy) or (sx > dx and sy < dy): char = '/' if (sx < dx and sy < dy) or (sx > dx and sy > dy): char = '\\' path = util.set_full_explore_map(game.current_map, False) libtcod.path_compute(path, sx, sy, dx, dy) while not libtcod.path_is_empty(path): cx, cy = libtcod.path_walk(path, False) libtcod.console_blit(game.con, 0, 0, game.MAP_WIDTH, game.MAP_HEIGHT, 0, game.MAP_X, game.MAP_Y) libtcod.console_put_char_ex(0, game.MAP_X + cx - game.curx, game.MAP_Y + cy - game.cury, char, libtcod.light_gray, libtcod.black) libtcod.console_flush() time.sleep(0.05) if trap: for obj in game.current_map.objects: if obj.x == dx and obj.y == dy and not obj.item: damage = util.roll_dice(1, 6) if obj.name == 'player': game.message.new('You are hit by an arrow for ' + str(damage) + ' pts of damage!', game.turns, libtcod.Color(160, 0, 0)) game.player.take_damage(damage, 'an arrow trap') else: obj.entity.take_damage(obj.x, obj.y, damage, 'an arrow', True)
def path_from_to(self, ox, oy, dx, dy): path = libtcod.path_new_using_function(MAP_WIDTH, MAP_HEIGHT, walk_compute, self.tiles, 1.41) libtcod.path_compute(path, ox, oy, dx, dy) return path
def largeRatAi(obj, ratHoleX, ratHoleY): # Handles movement and combat abilities of the large rat. if libtcod.map_is_in_fov(fovMap, obj.x, obj.y): if obj.distanceTo(player.x, player.y) >= 2: pathToPlayer = libtcod.path_new_using_map(fovMap, 1) libtcod.path_compute(pathToPlayer, obj.x, obj.y, player.x, player.y) newX, newY = libtcod.path_walk(pathToPlayer, True) if newX is not None: newX = newX - obj.x newY = newY - obj.y else: newX, newY = 0 libtcod.path_delete(pathToPlayer) if isWalkable(obj.x+newX, obj.y+newY): obj.move(obj.x+newX, obj.y+newY) else: player.alive.takeDamage(obj.alive.damage) else: if obj.distanceTo(ratHoleX, ratHoleY) <= 5: num = random.randint(0, len(offsets)-1) newX = offsets[num][0] newY = offsets[num][1] else: pathToHole = libtcod.path_new_using_map(fovMap, 1) libtcod.path_compute(pathToHole, obj.x, obj.y, ratHoleX, ratHoleY) newX, newY = libtcod.path_walk(pathToHole, True) if newX is not None: newX = newX - obj.x newY = newY - obj.y else: newX, newY = 0 libtcod.path_delete(pathToHole) if isWalkable(obj.x+newX, obj.y+newY): obj.move(obj.x+newX, obj.y+newY)
def compute_path(self, destination): sx, sy = self.parent.position.value dx, dy = destination libtcod.path_compute(self.path, sx, sy, dx, dy) self.clear() x, y = libtcod.path_walk(self.path, True) while not x is None: self.position_list.insert(0, (x, y)) x, y = libtcod.path_walk(self.path, True)
def path_effect(game,ox,oy,dx,dy,decay_time): libtcod.path_compute(game.path,ox,oy,dx,dy) px,py = ox,oy while not libtcod.path_is_empty(game.path): x,y = libtcod.path_walk(game.path,True) cell = line_directions[(px-x,py-y)] px,py = x,y p = Particle(x,y,decay_time,libtcod.yellow,cell,game.ticker,game.con) game.particles.append(p)
def find_path(source, target): fov_map = libtcod.map_new(Constants.MAP_WIDTH, Constants.MAP_HEIGHT) for y in range(Constants.MAP_HEIGHT): for x in range(Constants.MAP_WIDTH): libtcod.map_set_properties(fov_map, x, y, True, True) path = libtcod.path_new_using_map(fov_map, 1.5) libtcod.path_compute(path, source[0], source[1], target[0], target[1]) return path
def path_to(self, dx, dy): # use algorithm to move (A*) path = libtcod.path_new_using_map(fov_map,1.41) libtcod.path_compute(path, self.owner.x, self.owner.y, dx, dy) if not libtcod.path_is_empty(path): x,y = libtcod.path_walk(path,True) if not x is None: self.move_towards(x,y) libtcod.path_delete(path)
def move_towards(self, target_x, target_y): #Upgraded the move_towards to use the libtcod path algorythms and solving a bug #where the monsters "waited" near the doors #path = libtcod.path_new_using_map(fov_map,1) path = libtcod.path_new_using_function(MAP_WIDTH, MAP_HEIGHT, path_func, map, 1) libtcod.path_compute(path, self.x, self.y, target_x, target_y) (end_x,end_y) = libtcod.path_get(path, 0) dx = end_x - self.x dy = end_y - self.y self.move(dx, dy)
def connected_cells(source, target): my_path = libtcod.path_new_using_map(Engine.Fov.get_fov_map(), 1.41) libtcod.path_compute(my_path, source[0], source[1], target[0], target[1]) if not libtcod.path_is_empty(my_path): return True else: return False
def activate_autopilot(): options = map(lambda z: z.name, zones) index = menu('Autopilot to:\n', options, AUTOPILOT_WIDTH) if index is None: return None (x, y) = zones[index].center() path = libtcod.path_new_using_map(fov_map) libtcod.path_compute(path, player.x, player.y, x, y) return path
def compute_path(self, from_xy, to_xy, path_function): # for xy in level.map.rect().xy_values(): # tile = level.map[xy] # block_sight, blocked = tile.block_sight, tile.blocked # if self.allow_digging: # blocked = blocked and not tile.type == DIGGABLE # if self.avoid_solid_objects and xy != to_xy: # blocked = blocked or level.solid_object_at(xy) # if self.consider_unexplored_blocked: # blocked = blocked or not tile.explored # libtcod.map_set_properties(self.map, xy.x, xy.y, block_sight, not blocked) libtcod.path_compute(self.path, from_xy.x, from_xy.y, to_xy.x, to_xy.y)
def get_astar_distance_to(self, x, y, target_x, target_y): ''' Gets distance using A* algo - how far an entity would actually have to walk to get somewhere ''' # Handle case where the target is the same as the initial location if (x, y) == (target_x, target_y): return 0 # Otherwise, compute the path libtcod.path_compute(self.path_map, x, y, target_x, target_y) # A length of 0 here should mean that it was not possible to reach the location # It could mean that the initial loc == the target loc, but we've tested that above new_path_len = libtcod.path_size(self.path_map) # Therefore, a len of 0 here should mean unreachable - so return None return new_path_len if new_path_len else None
def process(self, game): visible =self.game.fov.is_visible(self.x, self.y) moved = False if visible: self.seen += 1 self.color = tcod.color_lerp(tcod.dark_gray, self.orig_color, (self.seen % 50) / 100.0) if self.seen % 50 == 0: self.game.duplicate(self) if self.seen == 200: self.character = 'o' self.movement = 0.4 elif self.seen == 400: self.character = 'O' self.movement = 0.6 path = tcod.path_new_using_map(self.game.fov.fov, 1.0) tcod.path_compute(path, self.x, self.y, self.game.player.x, self.game.player.y) if tcod.path_size(path) > 2: self.points += self.movement if self.points >= 1: self.points -= 1 x, y = tcod.path_get(path, 1) self.move(x - self.x, y - self.y) moved = True tcod.path_delete(path) if not moved: self.points += self.movement if self.points >= 1: self.points -= 1 movement = [ (0, 0), (0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, -1), (-1, 1), (1, -1) ] self.move(*random.choice(movement)) return True
def __init__(self, initial_location, target_location, entity, travel_verb='travel'): ActionBase.__init__(self) self.behavior = 'move' self.initial_location = initial_location self.target_location = target_location self.entity = entity self.travel_verb = travel_verb self.preconditions = [AmAvailableToAct(self.entity)] self.costs = {'money':0, 'time':0, 'distance':0, 'morality':0, 'legality':0} if g.WORLD: # This would otherwise stop this module running as __main__, leaving this in for testing purposes target_site = g.WORLD.tiles[self.target_location[0]][self.target_location[1]].site current_site = g.WORLD.tiles[self.entity.wx][self.entity.wy].site if target_site in g.WORLD.cities and current_site in g.WORLD.cities: full_path = current_site.path_to[target_site][:] else: # Default - use libtcod's A* to create a path to destination path = libtcod.path_compute(p=g.WORLD.path_map, ox=self.entity.wx, oy=self.entity.wy, dx=self.target_location[0], dy=self.target_location[1]) full_path = libtcod_path_to_list(path_map=g.WORLD.path_map) # Add path to brain self.entity.world_brain.path = full_path # Update the cost of this behavior self.costs['time'] += len(full_path) self.costs['distance'] += len(full_path) else: # Stuff to give this movement a random cost cost = roll(1, 10) self.costs['distance'] = cost self.costs['time'] = cost
def get_best_path(self, initial_location, target_location): ''' Find a path between 2 points, but take roads if both points happen to be cities ''' target_site = g.WORLD.tiles[target_location[0]][target_location[1]].site current_site = g.WORLD.tiles[initial_location[0]][initial_location[1]].site if target_site in g.WORLD.cities and current_site in g.WORLD.cities and current_site != target_site: full_path = current_site.path_to[target_site][:] else: # Default - use libtcod's A* to create a path to destination libtcod.path_compute(p=g.WORLD.path_map, ox=initial_location[0], oy=initial_location[1], dx=target_location[0], dy=target_location[1]) full_path = libtcod_path_to_list(path_map=g.WORLD.path_map) if not full_path: print '{0} -- has no full path to get from {1} to {2}'.format(self.entity.fulltitle(), self.initial_location, self.target_location) return full_path
def set_path(self): # there is no path, or the target has moved if self.path is None or (self.target_x, self.target_y) != libtcod.path_get_destination(self.path): self.path = libtcod.path_new_using_map(self.owner.map.libtcod_map, 1) # create the path; if failed, set path to None if not libtcod.path_compute(self.path, self.owner.x, self.owner.y, self.target_x, self.target_y): self.path = None
def initialize_fov(update=False): # print 'Loading/Generating map chunks...' # t0 = libtcod.sys_elapsed_seconds() game.traps = [] if not update: game.fov_map = libtcod.map_new(game.current_map.map_width, game.current_map.map_height) for y in range(game.current_map.map_height): for x in range(game.current_map.map_width): libtcod.map_set_properties(game.fov_map, x, y, not 'block_sight' in game.current_map.tile[x][y], 'explored' in game.current_map.tile[x][y] and not 'blocked' in game.current_map.tile[x][y]) else: for y in range(game.char.y - game.FOV_RADIUS, game.char.y + game.FOV_RADIUS): for x in range(game.char.x - game.FOV_RADIUS, game.char.x + game.FOV_RADIUS): if y < game.current_map.map_height and x < game.current_map.map_width: libtcod.map_set_properties(game.fov_map, x, y, not 'block_sight' in game.current_map.tile[x][y], 'explored' in game.current_map.tile[x][y] and not 'blocked' in game.current_map.tile[x][y]) if 'invisible' in game.current_map.tile[x][y] and game.current_map.tile[x][y]['type'] == 'trap' and libtcod.map_is_in_fov(game.fov_map, x, y): game.traps.append((x, y)) # compute paths using a*star algorithm game.path = libtcod.path_new_using_function(game.current_map.map_width, game.current_map.map_height, path_func) libtcod.path_compute(game.path, game.char.x, game.char.y, game.path_dx, game.path_dy)
def move_astar(self, target, entities, game_map): # Create a FOV map that has the dimensions of the map fov = libtcod.map_new(game_map.width, game_map.height) # Scan the current map each turn and set all the walls as unwalkable for y1 in range(game_map.height): for x1 in range(game_map.width): libtcod.map_set_properties(fov, x1, y1, not game_map.tiles[x1][y1].block_sight, not game_map.tiles[x1][y1].blocked) # Scan all the objects to see if there are objects that must be navigated around # Check also that the object isn't self or the target (so that the start and the end points are free) # The AI class handles the situation if self is next to the target so it will not use this A* function anyway for entity in entities: if entity.blocks and entity != self and entity != target: # Set the tile as a wall so it must be navigated around libtcod.map_set_properties(fov, entity.x, entity.y, True, False) # Allocate a A* path # The 1.41 is the normal diagonal cost of moving, it can be set as 0.0 if diagonal moves are prohibited my_path = libtcod.path_new_using_map(fov, 1.41) # Compute the path between self's coordinates and the target's coordinates libtcod.path_compute(my_path, self.x, self.y, target.x, target.y) # Check if the path exists, and in this case, also the path is shorter than 25 tiles # The path size matters if you want the monster to use alternative longer paths (for example through other rooms) if for example the player is in a corridor # It makes sense to keep path size relatively low to keep the monsters from running around the map if there's an alternative path really far away if not libtcod.path_is_empty(my_path) and libtcod.path_size(my_path) < 25: # Find the next coordinates in the computed full path x, y = libtcod.path_walk(my_path, True) if x or y: # Set self's coordinates to the next path tile self.x = x self.y = y else: # Keep the old move function as a backup so that if there are no paths (for example another monster blocks a corridor) # it will still try to move towards the player (closer to the corridor opening) self.move_towards(target.x, target.y, game_map, entities) # Delete the path to free memory libtcod.path_delete(my_path)
def create_path(self, gamemap_instance): """Creates the initial path_map, and then on subsequent calls uses that path_map to play.""" mymap = gamemap_instance.level if not self.is_pathmap_created: #Create the path map self.path_map = libtcod.map_new(MAP_WIDTH, MAP_HEIGHT) for x in range(1, MAP_WIDTH): for y in range(1, MAP_HEIGHT): libtcod.map_set_properties(self.path_map, x, y, not mymap[x][y].block_sight, not mymap[x][y].blocked) self.is_pathmap_created = True # now use the path map to create the path from the explorer's current position to another spot: self.path = libtcod.path_new_using_map(self.path_map) random_destination_x, random_destination_y = choose_random_unblocked_spot(mymap) libtcod.path_compute(self.path, self.owner.x, self.owner.y, random_destination_x, random_destination_y) originx, originy = libtcod.path_get_origin(self.path) destx, desty = libtcod.path_get_destination(self.path)
def move_towards(self, target_x, target_y): # libtcod CANNOT path into a blocked tile. # this is bad because this game treats mobs as blocked. # this allows mobs to path around each other # so, we won't change it # we will temporarily make the target tile unblocked # JUST for this computation # this is a terrible terrible terrible hack # but it works (hopefully) blocked = terrain.map.is_blocked(target_x, target_y) if blocked: tcod.map_set_properties(terrain.map.fov_map, target_x, target_y, True, True) tcod.path_compute(terrain.map.path, self.x, self.y, target_x, target_y) if blocked: terrain.map.update_fov_tile(target_x, target_y) (x, y) = tcod.path_walk(terrain.map.path, True) if not (x, y) == (None, None): dx, dy = (x - self.x, y - self.y) self.move(dx, dy)
def move_towards(self, target_x, target_y): global fov_map path = libtcod.path_new_using_map(fov_map) libtcod.path_compute(path, self.x, self.y, target_x, target_y) x,y = libtcod.path_get(path, 0) if x is None: self.move(0, 0) else: dx = int(round(target_x - x)) dy = int(round(target_y - y)) if dx != 0: dx = dx/abs(dx) if dy != 0: dy = dy/abs(dy) self.move(dx, dy) libtcod.path_delete(path)
def batAiUpdate(self, player): path = libtcod.path_compute(self.path, self.creature.x, self.creature.y, player.x, player.y) if path: length = libtcod.path_size(self.path) if length > 1:#self.creature.attackRange (x, y) = libtcod.path_walk(self.path, False) self.creature.moveTo(x, y) else: self.creature.attackCreature(player) else: pass
def Action_MoveTwoardsPlayer(self, attack = False, InternalParam = {}): #Adjaceny Test print "Adjacency Test" pX, pY = GameState.player.x, GameState.player.y dist = math.sqrt(math.pow(pX - self.x,2) + math.pow(pY - self.y,2)) if math.fabs(pX - self.x) < 1 and math.fabs(pY - self.y) <= 1: self.entity.melee_attack_entity(GameState.player.entity) return #if self.ObjectAdjacency(GameState.player): # self.entity.melee_attack_entity(GameState.player.entity) # return print "Passed" #Pov Test print "POV Test" if(self.Event_IsPlayerInPOV()): self.TargetLastSeenLocation = (GameState.player.x, GameState.player.y) if not self.move_towards(GameState.player.x, GameState.player.y): self.clearPath() self.TargetLastSeenPath = libtcod.path_new_using_function(cfg.MAP_WIDTH,cfg.MAP_WIDTH, self.path_func,(self.x,self.y)) libtcod.path_compute(self.TargetLastSeenPath,self.x,self.y,GameState.player.x,GameState.player.y) #self.TargetLastSeenPath = libtcod.path_new_using_map(GameState.fov_map) #Move Twoards Player elif self.TargetLastSeenPath and self.TargetLastSeenLocation != None: self.clearPath() self.TargetLastSeenPath = libtcod.path_new_using_function(cfg.MAP_WIDTH,cfg.MAP_WIDTH, self.path_func,(self.x,self.y)) x, y = self.TargetLastSeenLocation libtcod.path_compute(self.TargetLastSeenPath,self.x,self.y,x,y) if self.TargetLastSeenPath != None: x, y = self.TargetLastSeenLocation if(self.x, self.y) == (x,y): print "Giving Up Chase" self.clearPath() self.TargetLastSeenLocation = None return x,y = libtcod.path_walk(self.TargetLastSeenPath,False) if x != None and y != None: self.move_towards(x,y) print "Passed"
def move_to_target(self, Map): #dx = x - owner.x #dy = y - owner.y #distance = math.sqrt(dx ** 2 + dy ** 2) #dx = int(round(dx / distance)) #dy = int(round(dy / distance)) #self.owner.move(dx, dy) #if path doesnt exist make new path to target owner = self.owner target = owner.target fov_map = Map.fov_map path = libtcod.path_new_using_map(fov_map) libtcod.path_compute(path, owner.x, owner.y, target.x, target.y) # use the path ... if not libtcod.path_is_empty(path) : x,y=libtcod.path_walk(path,True) if not x is None : owner.put(x,y) owner.moved = True
def create_cave_maze(self, type, floor, wall, prob, oper): rooms = [0] * 2 for x in range(1, self.map_width - 1): for y in range(1, self.map_height - 1): if util.roll_dice(1, 100) < prob: self.set_tile_values(floor, x, y) for i in range(self.map_width * self.map_height * 5): x = libtcod.random_get_int(game.rnd, 1, self.map_width - 2) y = libtcod.random_get_int(game.rnd, 1, self.map_height - 2) if oper: if self.check_cell_neighbours(x, y) > 4: self.set_tile_values(wall, x, y) else: self.set_tile_values(floor, x, y) else: if self.check_cell_neighbours(x, y) > 4: self.set_tile_values(floor, x, y) else: self.set_tile_values(wall, x, y) # create rooms with up and down stairs x = libtcod.random_get_int(game.rnd, 2, self.map_width - 6) y = libtcod.random_get_int(game.rnd, 2, self.map_height - 6) rooms[0] = Rect(x, y, 5, 5) self.create_room(rooms[0], floor) (new_x1, new_y1) = rooms[0].center() game.char.x = new_x1 game.char.y = new_y1 count = 0 while (abs(x - new_x1) < 25) or (abs(y - new_y1) < 12): x = libtcod.random_get_int(game.rnd, 2, self.map_width - 6) y = libtcod.random_get_int(game.rnd, 2, self.map_height - 6) count += 1 if count == 50: return False rooms[1] = Rect(x, y, 5, 5) self.create_room(rooms[1], floor) (new_x2, new_y2) = rooms[1].center() # check if path to stairs is blocked if yes dig a tunnel path = util.set_full_explore_map(self, False) if not libtcod.path_compute(path, game.char.x, game.char.y, new_x2, new_y2): return False self.set_tile_values('stairs going up', game.char.x, game.char.y) self.up_staircase = (game.char.x, game.char.y) self.set_tile_values('stairs going down', new_x2, new_y2) self.down_staircase = (new_x2, new_y2) return True
def move_player(x, y): # Set globals. global turns, fov_recompute # Create path. player_path = roguelib.path_new_using_map(fov_map, 1.41) # Compute path to walk. roguelib.path_compute(player_path, player.x, player.y, x, y) while not roguelib.path_is_empty(player_path): xx, yy = roguelib.path_walk(player_path, True) if not is_blocked(xx, yy): # Move player. player.x = xx player.y = yy # Increase turns. turns += 1 # Recompute FOV. fov_recompute = True
def make_map(self, max_rooms, room_min_size, room_max_size, map_width, map_height, player, entities, tile_data): rooms = [] num_rooms = 0 center_of_last_room_x = None center_of_last_room_y = None for r in range(max_rooms): w = randint(room_min_size, room_max_size) h = randint(room_min_size, room_max_size) x = randint(0, map_width - w - 1) y = randint(0, map_height - h - 1) if randint(0, 1): #Make either a rectangular or circular room new_room = Room(x, y, w, h) else: new_room = Room.make_circle_room(x, y, min(w, h)) for other_room in rooms: if new_room.intersect(other_room): break else: self.place_room(new_room, tile_data) (new_x, new_y) = new_room.center() center_of_last_room_x = new_x center_of_last_room_y = new_y if num_rooms == 0: player.x = new_x player.y = new_y else: (prev_x, prev_y) = rooms[num_rooms - 1].center() if randint(0, 1) == 1: self.create_h_tunnel(prev_x, new_x, prev_y) self.create_v_tunnel(prev_y, new_y, new_x) else: self.create_v_tunnel(prev_y, new_y, prev_x) self.create_h_tunnel(prev_x, new_x, new_y) self.place_entities(new_room, entities) rooms.append(new_room) num_rooms += 1 stairs_component = Stairs(self.floor + 1) down_stairs = Entity(center_of_last_room_x, center_of_last_room_y, '>', lc.white, 'Stairs', render_order=RenderOrder.STAIRS, stairs=stairs_component) entities.append(down_stairs) #Check to make sure a path exists from the player to the down stairs fov_map = lc.map_new(self.width, self.height) for y in range(0, self.height): for x in range(0, self.width): lc.map_set_properties(fov_map, x, y, True, not self.tiles[x][y].blocked) lc.map_compute_fov(fov_map, 0, 0, 100, True, 0) path = lc.path_new_using_map(fov_map, 1) lc.path_compute(path, player.x, player.y, down_stairs.x, down_stairs.y) if lc.path_is_empty( path): #If no path exists, make a tunnel to the down stairs if randint(0, 1) == 1: self.create_h_tunnel(down_stairs.x, player.x, down_stairs.y) self.create_v_tunnel(down_stairs.y, player.y, player.x) else: self.create_v_tunnel(down_stairs.y, player.y, down_stairs.x) self.create_h_tunnel(down_stairs.x, player.x, player.y)
def findExplorePoint(self,world): if self.explored: return (False,False) #expecting a list t0 = time.time() px=self.x py=self.y ww=world.getWidth() wh=world.getHeight() # Scan in expanding circle outwards distance=1 edge=1 searchEffort=60 pathEffort=3 potentials=[] edges=[1,2,3,4] goodPath=False while not goodPath: while len(potentials)<=searchEffort: # scan edges for i in edges: for j in xrange(edge): [cx,cy]=self.edgeCalc(i,j,edge,distance) if cx<0 or cx>=ww: continue if cy<0 or cy>=wh: continue if world.isBlocked(cx,cy) or world.isSeen(cx,cy): continue #if world.isPathable(cx,cy): potentials.append((cx,cy)) #world.putThing(cx,cy) # and corners for i in edges: [cx,cy]=self.cornerCalc(i,distance,px,py) if cx<0 or cx>=ww: continue if cy<0 or cy>=wh: continue if world.isBlocked(cx,cy) or world.isSeen(cx,cy): continue #if world.isPathable(cx,cy): potentials.append((cx,cy)) #world.putThing(cx,cy) distance=distance+1 edge=edge+2 if distance>max(ww*2,wh*2): if len(potentials): break self.explored=True return (False,False) #print len(potentials) # now pop random for effort amount and pick shortest path distRank={} for cd in potentials: dst=abs(px-cd[0])+abs(py-cd[1]) while dst in distRank: dst=dst+1 distRank[dst]=cd potentials=[] dkKeys=sorted(distRank) for i in xrange(min(searchEffort,len(dkKeys))): potentials.append(distRank[dkKeys[i]]) #world.putThing(potentials[i][0],potentials[i][1]) pselect=random.sample(potentials,min(pathEffort,len(dkKeys))) distRank={} if not self.pathMap: self.pathMap=world.getBlockedMap() for cd in pselect: #world.putThing(cd[0],cd[1],"*") path=libtcod.path_new_using_map(self.pathMap,0) libtcod.path_compute(path,self.x,self.y,cd[0],cd[1]) ps=libtcod.path_size(path) if ps==0: print "Zero-len path:",cd,px,py print "Is blocked:",world.isBlocked(cd[0],cd[1]) print "Is pathable:",world.isPathable(cd[0],cd[1]) print "Is seen:",world.isSeen(cd[0],cd[1]) while ps in distRank: ps=ps+1 distRank[ps]=(cd,path) # get closest path len - if it is very high compared to distance, reject and expand search dkKeys=sorted(distRank) if dkKeys[0] < distance*4 and dkKeys[0]>0: ret=distRank[dkKeys[0]] goodPath=True print "Successful search at pl",dkKeys[0],"distance",distance,"took",int(math.floor((time.time()-t0)*1000)),"ms" else: print "Rejected search at pl",dkKeys[0],"distance",distance,"took",int(math.floor((time.time()-t0)*1000)),"ms" return ret
def map_init_dungeon(width, height): def path_cost(xFrom, yFrom, xTo, yTo, alg_array): if alg_array[xTo][yTo] == 0: return 1 if alg_array[xTo][yTo] == 3: return 0.01 else: return 10 room_prefabs_10x10 = [] f = open('resources/map_prefabs/map_prefabs[10x10].csv', 'r').read().split('\n') # 10x10 for i in range(len(f[0]) // 10): for j in range(len(f) // 10): room = '' for y in range(10): for x in range(10): room += f[j * 10 + x][i * 10 + y] room_prefabs_10x10.append(room) room_prefabs_5x5 = [] f = open('resources/map_prefabs/map_prefabs[5x5].csv', 'r').read().split('\n') # 10x10 for i in range(len(f[0]) // 5): for j in range(len(f) // 5): room = '' for y in range(5): for x in range(5): room += f[j * 5 + x][i * 5 + y] room_prefabs_5x5.append(room) monsters_pool = [[game_content.m_slime], []] alg_array = [[0 for j in range(height)] for i in range(width)] terrain = [[0 for j in range(height)] for i in range(width)] items = [] entities = [] creatures = [] rooms = [] room_exits = [] room_connections = [] rooms_size = [(10, 10), (5, 5)] rooms.append((width // 2 - 3, height // 2 - 3, 6, 6)) for x in range(width // 2 - 3, width // 2 + 3): for y in range(height // 2 - 3, height // 2 + 3): if y == height // 2 and (x == width // 2 - 3 or x == width // 2 + 3): alg_array[x][y] = 7 room_exits.append((x, y, -1)) else: alg_array[x][y] = 2 available_spots = [ (x, y) for x in range(width) for y in range(height) if x > 6 and x < width - 12 and y > 6 and y < height - 12 ] for x in range(len(available_spots)): append = True i, j = available_spots.pop(random.randint(0, len(available_spots) - 1)) w, h = random.choice(rooms_size) newRoom = (i, j, w, h) #X, Y, W, H for room in rooms: if util.rectangle_intersects(newRoom, room): append = False if append == True: rooms.append(newRoom) for roomIndex in range(len(rooms))[0:]: room = rooms[roomIndex] if room[2] == 10 and room[3] == 10: room_layout = random.choice(room_prefabs_10x10) for x in range(room[2]): for y in range(room[3]): alg_array[x + room[0]][y + room[1]] = int( room_layout[x * 10 + y]) if int(room_layout[x * 10 + y]) == 7: room_exits.append( (x + room[0], y + room[1], roomIndex)) elif room[2] == 5 and room[3] == 5: room_layout = random.choice(room_prefabs_5x5) for x in range(room[2]): for y in range(room[3]): alg_array[x + room[0]][y + room[1]] = int( room_layout[x * 5 + y]) if int(room_layout[x * 5 + y]) == 7: room_exits.append( (x + room[0], y + room[1], roomIndex)) for exit_init in room_exits: path = libtcodpy.path_new_using_function(width, height, path_cost, alg_array, 0) other_exits = sorted([ exit_other for exit_other in room_exits if exit_other[2] != exit_init[2] and ( exit_other[2], exit_init[2]) not in room_connections ], key=lambda e: util.simpledistance( (exit_init[0], exit_init[1]), (e[0], e[1]))) if len(other_exits) > 0: exit_end = other_exits[0] else: exit_end = sorted([ exit_other for exit_other in room_exits if exit_other[2] != exit_init[2] ], key=lambda e: util.simpledistance( (exit_init[0], exit_init[1]), (e[0], e[1])))[0] room_connections.append((exit_init[2], exit_end[2])) room_connections.append((exit_end[2], exit_init[2])) libtcodpy.path_compute(path, exit_init[0], exit_init[1], exit_end[0], exit_end[1]) for i in range(libtcodpy.path_size(path) - 1): x, y = libtcodpy.path_get(path, i) alg_array[x][y] = 3 for x in range(len(alg_array)): for y in range(len(alg_array[x])): if alg_array[x][y] in [0, 1]: terrain[x][y] = game_content.t_cave_wall(x, y) else: terrain[x][y] = game_content.t_cave_floor(x, y) if alg_array[x][y] == 4: creatures.append( random.choice(monsters_pool[GAME.level])(x, y)) if alg_array[x][y] == 7: entities.append( game_content.n_door( x, y, game_content.SPRITESHEET_ENTITIES.image_at( (0, 32, 32, 32)), game_content.SPRITESHEET_ENTITIES.image_at( (32, 32, 32, 32), colorkey=game_constants.COLOR_COLORKEY))) terrain[x][y].passable = False terrain[x][y].transparent = False return terrain, items, entities, creatures
def compute_path(self, from_xy, to_xy, path_function): libtcod.path_compute(self.path, from_xy.x, from_xy.y, to_xy.x, to_xy.y)