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 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 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 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 takepath(self): # libtcod.path_compute(game.player.path, game.player.destination[0], game.player.destination[1], ...) if libtcod.path_is_empty(self.path): return "empty" else: x, y = libtcod.path_get(self.path, 0) self.owner.x, self.owner.y = libtcod.path_walk(self.path, True) return "pathing"
def libtcod_path_to_list(path_map): ''' get a libtcod path into a list ''' path = [] while not libtcod.path_is_empty(path_map): x, y = libtcod.path_walk(path_map, True) path.append((x, y)) return path
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 move(self): if self.move_stat != 50 - self.speed: self.move_stat += 1 return else: self.move_stat = 0 if not libtcod.path_is_empty(self.path): self.x,self.y = libtcod.path_walk(self.path, True)
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 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 test(self, abs_src_x, abs_src_y, abs_dst_x, abs_dst_y): self.compute_path_abs(abs_src_x, abs_src_y, abs_dst_x, abs_dst_y) if libtcod.path_is_empty(self.path): log.info("Path is empty") while True: loc = libtcod.path_walk(self.path, False) if loc != (None, None): loc_abs = (loc[0] + self.x_start, loc[1] + self.y_start) log.info("abs ({},{})".format(*loc_abs)) #print("({},{})".format(*loc)) else: break
def takepath(self, game): #libtcod.path_compute(game.player.path, game.player.destination[0], game.player.destination[1], ...) if libtcod.path_is_empty(self.path): return 'empty' else: #x,y = libtcod.path_get(self.path, 0) x, y = libtcod.path_walk(self.path, True) if (x, y) == (None, None): return 'empty' self.owner.x, self.owner.y = x, y #if self.move(game, dx, dy) == 'blocked': #return 'empty' return 'pathing'
def move(self, facility): """Follow the current path toward a given direction.""" x,y = libtcod.path_walk(self.currentPath, False) if x is not None: self.location.moveTowards(x - self.location.x, y - self.location.y) else: # Path has been followed : delete it ! libtcod.path_delete(self.currentPath) self.currentPath = None # STOP THE MOVEMENT ! self.location.freeze() if self.currentTask is not None: self.set_behaviour(EmployeeBehaviour.TASK_DO) else: self.set_behaviour(EmployeeBehaviour.WANDER)
def take_turn(self,game): #a basic monster takes its turn. if you can see it, it can see you self.owner.fighter.ticker.schedule_turn(self.owner.fighter.speed,self.owner) if libtcod.map_is_in_fov(game.fov_map, self.owner.x, self.owner.y): #move towards player if far away if self.owner.distance_to(game.player) >= 2: #we need to get the closest distance from the monster, surrounding the player dx,dy = get_next_to_player(self,game.player,game.Map.map) #then move to it if libtcod.path_compute(game.path,self.owner.x,self.owner.y,dx,dy): x,y = libtcod.path_walk(game.path,True) self.owner.x = x self.owner.y = y #close enough, attack! (if the player is still alive.) elif game.player.fighter.hp > 0: self.owner.fighter.attack(game.player) else:#start wandering self.owner.ai = WanderingMonster(x=self.owner.x,y=self.owner.y) self.owner.ai.owner = self.owner
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 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_astar(self, target, entities, game_map): # create a fov map at the dimensions of the map fov = libtcod.map_new(game_map.width, game_map.height) # scan current map each turn and set all 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 objets to see if there are objects that must be navigated around. # check also if object isn't self or the target for entity in entities: if entity.blocks and entity != self and entity != target: #set the tile as a wall so it muyst be navigated around libtcod.map_set_properties(fov, entity.x, entity.y, True, False) # allocate a A* path # 1.31 normal diag cost of moving, to put to 0 if diagonal forbiden my_path = libtcod.path_new_using_map(fov, 1.41) # compute path between self coordinates and the target coordinate libtcod.path_compute(my_path, self.x, self.y, target.x, target.y) # check if path exists && shorter than 25 tiles if not libtcod.path_is_empty( my_path) and libtcod.path_size(my_path) < 25: # find next coordinates in the computed full path x, y = libtcod.path_walk(my_path, True) if x or y: # set self coordinates to the next path tile self.x = x self.y = y else: # old move function if no path self.move_towards(target.x, target.y, game_map, entities) # delete the path to free memeory libtcod.path_delete(my_path)
def take_turn(self, game): #a basic monster takes its turn. if you can see it, it can see you self.owner.fighter.ticker.schedule_turn(self.owner.fighter.speed, self.owner) if libtcod.map_is_in_fov(game.fov_map, self.owner.x, self.owner.y): #move towards player if far away if self.owner.distance_to(game.player) >= 2: #we need to get the closest distance from the monster, surrounding the player dx, dy = get_next_to_player(self, game.player, game.Map.map) #then move to it if libtcod.path_compute(game.path, self.owner.x, self.owner.y, dx, dy): x, y = libtcod.path_walk(game.path, True) self.owner.x = x self.owner.y = y #close enough, attack! (if the player is still alive.) elif game.player.fighter.hp > 0: self.owner.fighter.attack(game.player) else: #start wandering self.owner.ai = WanderingMonster(x=self.owner.x, y=self.owner.y) self.owner.ai.owner = self.owner
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 test_astar(map_): astar = libtcodpy.path_new_using_map(map_) assert not libtcodpy.path_compute(astar, *POINTS_AC) assert libtcodpy.path_size(astar) == 0 assert libtcodpy.path_compute(astar, *POINTS_AB) assert libtcodpy.path_get_origin(astar) == POINT_A assert libtcodpy.path_get_destination(astar) == POINT_B libtcodpy.path_reverse(astar) assert libtcodpy.path_get_origin(astar) == POINT_B assert libtcodpy.path_get_destination(astar) == POINT_A assert libtcodpy.path_size(astar) != 0 assert libtcodpy.path_size(astar) > 0 assert not libtcodpy.path_is_empty(astar) for i in range(libtcodpy.path_size(astar)): x, y = libtcodpy.path_get(astar, i) while (x, y) != (None, None): x, y = libtcodpy.path_walk(astar, False) libtcodpy.path_delete(astar)
def move_astar(self, target): # Create a FOV map for the actor in question fov = tcod.map_new(settings.MAP_WIDTH, settings.MAP_HEIGHT) # Scan the current map and set all walls as unwalkable for y1 in range(settings.MAP_HEIGHT): for x1 in range(settings.MAP_WIDTH): tcod.map_set_properties( fov, x1, y1, not settings.dungeon_map[x1][y1].block_sight, not settings.dungeon_map[x1][y1].blocked) # Scan all objects to see if anything must be navigated around # Check also that the object isn't self or the target (so that start and endpoints are free) for obj in settings.objects: if obj.blocks and obj != self and obj != target: tcod.map_set_properties(fov, obj.x, obj.y, True, False) # Allocating the A* path # The 1.41 is the normal diagonal cost of moving. my_path = tcod.path_new_using_map(fov, 1.41) tcod.path_compute(my_path, self.x, self.y, target.x, target.y) # Check if the path exists and is shorter than 25 tiles # The path size matters for the monster to use alternative longer paths (player in another room, corridor, etc) # If the path size is too big monsters will run weird routes around the map if not tcod.path_is_empty(my_path) and tcod.path_size(my_path) < 25: x, y = tcod.path_walk(my_path, True) if x or y: # set self's coords to the next path tile self.combatant.set_direction(x - self.x, y - self.y) self.x = x self.y = y else: self.move_towards(target.x, target.y) tcod.path_delete(my_path)
def take_turn(self, gamemap_instance): mymap = gamemap_instance.level object_list = gamemap_instance.objects if not self.is_pathmap_created: self.create_path(gamemap_instance) if not libtcod.path_is_empty(self.path): pathx, pathy = libtcod.path_walk(self.path, True) #print 'Explorer is trying to move from (' + str(self.owner.x) + ', ' + str(self.owner.y) + #') to (' + str(pathx) + ', ' + str(pathy) +').' dx = pathx - self.owner.x dy = pathy - self.owner.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, self.owner, dx, dy) else: #print 'The Explorer ' + self.owner.name + ' has finished their path. Choosing a new one...' self.create_path(gamemap_instance)
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 move_astar(self, target, entities, game_map): fov = lcod.map_new(game_map.width, game_map.height) for x in range(game_map.width): for y in range(game_map.height): lcod.map_set_properties(fov, x, y, not game_map.tiles[x][y].block_sight, not game_map.tiles[x][y].blocked) for entity in entities: if entity.blocks and entity != self and entity != target: lcod.map_set_properties(fov, entity.x, entity.y, True, False) my_path = lcod.path_new_using_map(fov, 1.41) lcod.path_compute(my_path, self.x, self.y, target.x, target.y) if not lcod.path_is_empty(my_path) and lcod.path_size(my_path) <= 25: x, y = lcod.path_walk(my_path, True) if x or y: self.x = x self.y = y else: self.move_towards(target, game_map, entities) lcod.path_delete(my_path)
def get_coord_abs(self): x, y = libtcod.path_walk(self.path, False) abs_x = x + self.x_start abs_y = y + self.y_start return abs_x, abs_y
speed = [1, 0] elif key.vk == tcod.KEY_ESCAPE: if not alive: init = True restart = True else: break if demo: # find a snack if not found: found, pathx, pathy = snackxy(grid, CW, CH) if found: #path = tcod.path_new_using_map(grid, 0) if tcod.path_compute(path, snake[0].x, snake[0].y, pathx, pathy): #x, y = tcod.path_get(path, 0) x, y = tcod.path_walk(path, False) if x is not None: speed = [x - snake[0].x, y - snake[0].y] else: found = False # no path else: # you're f****d found = False if not found: # no snack on grid (yet?) x = snake[0].x + speed[0] y = snake[0].y + speed[1] if not tcod.map_is_walkable(grid, x, y): # try up speed = [0, -1]
def take_turn(self, gamemap_instance): """ Current bugs: 1) The worked-on Tile doesn't turn to gravel- why not? 2) The loop doesn't really go back around. They don't pick a new target, especially if they get stuck while walking. They just give up after the first time they bump into something dynamic. """ fov_map = gamemap_instance.fov_map object_list = gamemap_instance.objects mymap = gamemap_instance.level if not self.is_pathmap_created: print 'Builder needs to create_path' self.create_path(gamemap_instance) if not libtcod.path_is_empty(self.path): pathx, pathy = libtcod.path_walk(self.path, True) #print 'Explorer is trying to move from (' + str(self.owner.x) + ', ' + str(self.owner.y) + #') to (' + str(pathx) + ', ' + str(pathy) +').' dx = pathx - self.owner.x dy = pathy - self.owner.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, self.owner, dx, dy) elif self.work_target[0] is not None: (x, y) = self.work_target (my_x, my_y) = self.owner.x, self.owner.y # The following logic checks to see if they are standing in any of the 8 squares around # the target Tile. I definitely had to draw a diagram for this. if ((my_x+1 == x) and ( (my_y+1 == y) or (my_y == y) or (my_y-1 == y)) ) \ or ((my_x == x) and ( (my_y+1 == y) or (my_y == y) or (my_y-1 == y)) ) \ or ((my_x-1 == x) and ( (my_y+1 == y) or (my_y == y) or (my_y-1 == y)) ): # We have arrived at a Tile that needs work done. Now begin work: print 'Builder is standing at (' + str(my_x) +', '+ str(my_y)+') ' \ 'and is beginning work at (' + str(x) + ', ' + str(y) +').' # Using a switch statement here because eventually there will be other states like # 'building' or 'installing' something, etc for case in switch(mymap[x][y].designation_type): if case('clearing'): mymap[x][y].blocked = False mymap[x][y].block_sight = False mymap[x][y].fore = color_ground mymap[x][y].back = color_ground mymap[x][y].char = GRAVEL # Then reset the tile: mymap[x][y].designated = False mymap[x][y].designation_type = None mymap[x][y].designation_char = None mymap[x][y].being_worked_on = False #gamemap_instance.initialize_fov() print 'Finished work, resetting work_target to None, None.' self.work_target = (None, None) self.is_pathmap_created = False break if case(): break # default else: self.pick_spot_to_work(gamemap_instance) self.create_path(gamemap_instance)
def path_step(path): x,y=libtcod.path_walk(path, True) return x,y
def playerInput(): # Handles reacting to player input. global fovCompute, turns, actionMenu, gameState, widgets for widget in widgets: if widget.console != topGuiConsole: widget.checkSelected(mouse.cx, mouse.cy-topGuiHeight) else: widget.checkSelected(mouse.cx, mouse.cy) if mouse.lbutton_pressed: if actionMenu[0]: if mouse.cx > actionMenu[3] and mouse.cx < actionMenu[3]+actionWidth: if mouse.cy-topGuiHeight > actionMenu[4] and mouse.cy-topGuiHeight < actionMenu[4]+actionHeight: for widget in widgets: if widget.selected: if actionMenu[5] == "stairs": widget.action() else: widget.action(player, actionMenu[1], actionMenu[2]) # Deletes all widgets created for action menu and resets action menu container. actionMenu = [False, 0, 0, 0, 0, ""] del widgets[2:6] return "ENDTURN" else: if libtcod.map_is_in_fov(fovMap, mouse.cx, mouse.cy-topGuiHeight) and gameState == "ACTIVE": if isWalkable(mouse.cx, mouse.cy-topGuiHeight): if player.distanceTo(mouse.cx, mouse.cy-topGuiHeight) >= 2: pathToCoords = libtcod.path_new_using_map(fovMap, 1) libtcod.path_compute(pathToCoords, player.x, player.y, mouse.cx, mouse.cy-topGuiHeight) while not libtcod.path_is_empty(pathToCoords): newX, newY = libtcod.path_walk(pathToCoords, True) if newX is not None: newX = newX - player.x newY = newY - player.y player.move(player.x+newX, player.y+newY) turns += 1 if isNpcInFov(): break libtcod.path_delete(pathToCoords) fovCompute = True return "ENDTURN" else: player.move(mouse.cx, mouse.cy-topGuiHeight) turns += 1 fovCompute = True return "ENDTURN" if not actionMenu[0]: for widget in widgets: if widget.selected: widget.action() if mouse.rbutton_pressed: if actionMenu[0]: # Deletes all widgets created for action menu and resets action menu container. actionMenu = [False, 0, 0, 0, 0, ""] del widgets[2:6] elif gameState != "ACTIVE": gameState = "ACTIVE" widgets = widgets[0:2] else: if libtcod.map_is_in_fov(fovMap, mouse.cx, mouse.cy-topGuiHeight): getAction(mouse.cx, mouse.cy-topGuiHeight) fovCompute = True if key.pressed and key.vk == libtcod.KEY_SPACE: displayMsgHistory() if key.vk == libtcod.KEY_ESCAPE: if actionMenu[0]: # Deletes all widgets created for action menu and resets action menu container. actionMenu = [False, 0, 0, 0, 0, ""] del widgets[2:6] if gameState != "ACTIVE": gameState = "ACTIVE" widgets = widgets[0:2] return False
def play_game(): global key, mouse, autopilot_on mouse = libtcod.Mouse() key = libtcod.Key() autopilot_on = False tutorial = True while not libtcod.console_is_window_closed(): if game_state == GAME_STATE_VICTORY or game_state == GAME_STATE_PLAYER_DEAD: break libtcod.sys_check_for_event(libtcod.EVENT_KEY_PRESS | libtcod.EVENT_MOUSE, key, mouse) libtcod.console_set_default_foreground(0, libtcod.white) renderer.render_all(player=player, objects=objects, game_map=game_map, con=con, panel=panel, projectiles=projectiles, game_msgs=game_msgs, dungeon_level=dungeon_level, mouse=mouse, non_interactive_objects=non_interactive_objects) libtcod.console_flush() renderer.clear_objects(con, objects) renderer.clear_objects(con, projectiles) if tutorial: msgbox("Welcome to the game!\n\n" "You're tasked with a very important mission! The most talented diplomat the Earthlings have is " "travelling to Epsilon Gruis I, where he'll attend peace talks with The Safe Ones and possibly gain " "their support! Obviously this cannot happen, so you must ASSASSINATE THE DIPLOMAT!\n\n" "To reach the diplomat, you must navigate through nine sectors (all crawling with hostiles by the " "way) by using the naturally occurring JUMP POINTS. Our spies have provided INTEL pickups on the way" " that will give you the disposition of the enemy forces in the next sector. If you don't pick up " "the INTEL you'll be flying blind and probably die!\n\n" "Your ship is equipped with a 3-tile cutting laser. End your turn within a distance of 3 to an enemy" " to attack. It's pretty powerful against small ships, but be wary of extended engagements.\n\n" "Good luck captain!\n\n" "CONTROLS:\n" "KEYPAD: Movement\n" "a: autopilot to zone\n" "g: pick up an item in your tile\n" "i: view inventory and use items\n" "d: drop items\n" "r: view sector reports (DO THIS)\n" "<: jump to the next sector (must be on the jump point)\n" "ESC: quit to menu", 70) tutorial = False # TODO: Kind of messy way of structuring this! time = time_to_next_event(objects, projectiles) for obj in objects: if obj.fighter and (obj.ai or obj == player): obj.fighter.pass_time(time) for projectile in projectiles: projectile.fighter.pass_time(time) # Take turn if not autopiloting if player.fighter.time_until_turn == 0 and not autopilot_on: check_level_up() player_action = handle_keys() if player_action == 'exit': break elif player_action != GAME_STATE_DIDNT_TAKE_TURN: player.fighter.end_turn() # Autopilot elif player.fighter.time_until_turn == 0: # Check if there are nearby enemies nearest = closest_monster(TORCH_RADIUS) if key.vk != libtcod.KEY_NONE: autopilot_on = False message('Disengaging autopilot on pilot input!') if nearest: autopilot_on = False message('Enemy ships nearby! Autopilot disengaging!') elif libtcod.path_is_empty(autopilot_path): autopilot_on = False message('You have reached your destination! Autopilot disengaging!') else: (x, y) = libtcod.path_walk(autopilot_path, False) player.move_towards(x, y, game_map, objects) player.fighter.end_turn() else: player_action = None if game_state == GAME_STATE_PLAYING and player_action != GAME_STATE_DIDNT_TAKE_TURN: for o in objects: if o.fighter and o.fighter.time_until_turn == 0 and o.ai: o.ai.take_turn() o.fighter.end_turn() for projectile in projectiles: if projectile.fighter.time_until_turn == 0: projectile.ai.take_turn() projectile.fighter.end_turn()
def read_path(self, path, limit): if not libtcod.path_is_empty(path): if libtcod.path_size(path) <= limit: x, y = libtcod.path_walk(path, True) return [x, y] libtcod.path_delete(path)
def eNextStepPath(event): if event.Owner.Path: x, y = Libtcod.path_walk(event.Owner.Path, True) if not x is None: event.Owner.Move(x - event.Owner.X, y - event.Owner.Y)
def direct_path(ox, oy, dx, dy, map): path = T.path_new_using_map(map) T.path_compute(path, ox, oy, dx, dy) (nx, ny) = T.path_walk(path, False) return (nx - ox, ny - oy)
def generate_river(): river_start_x = 0 river_start_y = 0 river_end_x = MAP_WIDTH - 1 river_end_y = MAP_HEIGHT - 1 river_noise = [[0 for y in range(MAP_WIDTH)] for x in range(MAP_HEIGHT)] for i in range(MAP_HEIGHT): river_noise[i] = map(lambda a: (2+a)**4, noise_map[i]) # scaled up def river_cost(xFrom, yFrom, xTo, yTo, river_noise): return river_noise[yTo][xTo] path = libtcod.path_new_using_function(MAP_WIDTH, MAP_HEIGHT, river_cost, river_noise) # wish I could just use # (lambda xFrom, yFrom, xTo, yTo, river_noise: river_noise[xTo][yTo]) libtcod.path_compute(path, river_start_x, river_start_y, river_end_x, river_end_y) while not libtcod.path_is_empty(path): x, y = libtcod.path_walk(path, True) g.level_map[y][x] = Tile(tile_types.SHALLOW_WATER) # make a wider river by making all the neighbors water # we need to initialize these separately, but I don't know why x_in_min = False x_in_max = False y_in_min = False y_in_max = False if x-1 >= 0: x_in_min = True if x+1 < MAP_WIDTH: x_in_max = True if y-1 >= 0: y_in_min = True if y+1 < MAP_HEIGHT: y_in_max = True # left if x_in_min: g.level_map[y][x-1] = Tile(tile_types.SHALLOW_WATER) # bottom left if y_in_min: g.level_map[y-1][x-1] = Tile(tile_types.SHALLOW_WATER) # top left if y_in_max: g.level_map[y+1][x-1] = Tile(tile_types.SHALLOW_WATER) # right if x_in_max: g.level_map[y][x+1] = Tile(tile_types.SHALLOW_WATER) # bottom right if y_in_min: g.level_map[y-1][x+1] = Tile(tile_types.SHALLOW_WATER) # top right if y_in_max: g.level_map[y+1][x+1] = Tile(tile_types.SHALLOW_WATER) # bottom if y_in_min: g.level_map[y-1][x] = Tile(tile_types.SHALLOW_WATER) # top if y_in_max: g.level_map[y+1][x] = Tile(tile_types.SHALLOW_WATER) # Iterate through all the tiles. Remove trees on shallow water tiles. for j in range(MAP_HEIGHT): for i in range(MAP_WIDTH): if g.level_map[j][i].type == tile_types.SHALLOW_WATER: for feature in g.terrain_features: if feature.x == i and feature.y == j: g.terrain_features.remove(feature)
def take_turn(self): self.get_target() # we have a target if self.target: # target is close enough to attack if self.owner.distance_to_actor(self.target) == 1: self.unset_temp_blocking() return self.owner.melee_attack(self.target) # too far to attack, so try to chase else: self.set_path() # if there is a path, try to walk along it if self.path: # the path is empty, remove the target if libtcod.path_is_empty(self.path): self.target = None self.target_x = None self.target_y = None self.path = None return False # try to walk the path else: x, y = libtcod.path_walk(self.path, False) if x is None: self.path = None return False actor = self.owner.map.actor_at(x, y) feature = self.owner.map.feature_at(x, y) # there is an actor in the way if actor: self.path = None self.set_temp_blocking(actor) return False # there is a closed door in the way, open it elif self.owner.opens_doors and feature.is_door and feature.open == False: self.path = None self.unset_temp_blocking() return feature.interact(self.owner) # otherwise, the space is free; move to that space else: self.owner.move_to(x, y) self.unset_temp_blocking() return True # no path, so just do nothing else: for actor in self.temporary_blocking: if actor.faction == 'neutral' and self.owner.distance_to_actor(actor) == 1: self.owner.melee_attack(actor) self.unset_temp_blocking() return True