def Update(self): "Take one action" pc = Global.pc #TODO: Generalize this to follow any mob, not just PC. if self.state == "wander": if self.dir == None: self.PickNewDirection() if self.mob.can_see_pc: self.state = "chase" return else: blocker = self.mob.SquareBlocked(self.mob.x+self.dx, self.mob.y+self.dy) if blocker is None: self.mob.Walk(self.dx, self.dy) return # The square is blocked; see if it's an openable door: if isinstance(blocker, dungeons.Door): if self.mob.can_open_doors: if not blocker.Open(self.mob): # Tried and failed to open the door; waste some time: self.mob.Walk(0, 0) return self.PickNewDirection() return elif self.state == "chase": if adjacent(self.mob, pc): self.mob.Attack(pc) return if self.mob.can_see_pc: self.tx, self.ty = pc.x, pc.y else: if (self.mob.x, self.mob.y) == (self.tx, self.ty): # We're at the last place we saw the @, and we still can't see him: log("%s lost sight of its prey." % self.mob.name) self.state = "wander" return # We can see the PC, but are not in melee range: use A*: path = astar.path(self.mob.x, self.mob.y, self.tx, self.ty, self.mob.PathfindPass, max_length=10) if path: dx, dy = path[0][0] - self.mob.x, path[0][1] - self.mob.y self.mob.Walk(dx, dy) log("%s found a path from (%s, %s) to (%s, %s) %s." % (self.mob.name, self.mob.x, self.mob.y, self.tx, self.ty, path)) return else: log("%s failed pathfinding." % self.mob.name) # Pathfinding failed, but we can see the @...just sit there and be mad: self.mob.Walk(0, 0) return
def get_path(self, start, goal, local=True, unoccupied=False, max_path_len=None, max_time=None): #log.debug("get_path: g =\n %s" % str(g)) if (start, goal) in self.paths: log.debug(" returning cached path: %s -> %s" % (start, goal)) return self.paths[(start, goal)] graph_h = self.ants.rows graph_w = self.ants.cols rmin, rmax = [f(start[0], goal[0]) for f in [min, max]] cmin, cmax = [f(start[1], goal[1]) for f in [min, max]] in_graph = make_in_graph(rmin, rmax+1, cmin, cmax+1) passable = self.ants.passable if not unoccupied else \ lambda p: self.ants.passable(p) and self.ants.unoccupied(p) if local: def adjacent(node): #log.debug("adjacent: %s" % str(node)) r, c = node return filter(lambda p: in_graph(p) and passable(p), [ (r, c-1), (r, c+1), (r-1, c), (r+1, c) ]) else: def adjacent(node): #log.debug("adjacent: %s" % str(node)) r, c = node return filter(passable, [ (r, (c-1) % self.ants.cols), (r, (c+1) % self.ants.cols), ((r-1) % self.ants.rows, c), ((r+1) % self.ants.rows, c) ]) p = astar.path(self.ants.map, start, goal, adjacent, self.ants.distance, astar.h_simple, max_path_len=max_path_len, max_time=max_time) #astar.h_cross) #log.debug("get_path: path =\n %s" % str(p)) #dump_path("path_%s_%s_%s.dat" % (start, goal, time.time()), #graph, start, goal, p, passable=passable) return p