func (a *Move) AiMoveToPos(ent *game.Entity, dst []int, max_ap int) game.ActionExec { base.Log().Printf("PATH: Request move to %v", dst) graph := ent.Game().Graph(ent.Side(), false, nil) src := []int{ent.Game().ToVertex(ent.Pos())} _, path := algorithm.Dijkstra(graph, src, dst) base.Log().Printf("PATH: Found path of length %d", len(path)) ppx, ppy := ent.Pos() if path == nil { return nil } _, xx, yy := ent.Game().FromVertex(path[len(path)-1]) base.Log().Printf("PATH: %d,%d -> %d,%d", ppx, ppy, xx, yy) if ent.Stats.ApCur() < max_ap { max_ap = ent.Stats.ApCur() } path = limitPath(ent, src[0], path, max_ap) _, xx, yy = ent.Game().FromVertex(path[len(path)-1]) base.Log().Printf("PATH: (limited) %d,%d -> %d,%d", ppx, ppy, xx, yy) if len(path) <= 1 { return nil } var exec moveExec exec.SetBasicData(ent, a) exec.Path = path return &exec }
func distBetweenEnts(e1, e2 *game.Entity) int { x1, y1 := e1.Pos() dx1, dy1 := e1.Dims() x2, y2 := e2.Pos() dx2, dy2 := e2.Dims() var xdist int switch { case x1 >= x2+dx2: xdist = x1 - (x2 + dx2) case x2 >= x1+dx1: xdist = x2 - (x1 + dx1) default: xdist = 0 } var ydist int switch { case y1 >= y2+dy2: ydist = y1 - (y2 + dy2) case y2 >= y1+dy1: ydist = y2 - (y1 + dy1) default: ydist = 0 } if xdist > ydist { return xdist } return ydist }
func (a *AoeAttack) AiBestTarget(ent *game.Entity, extra_dist int, spec AiAoeTarget) (x, y int, targets []*game.Entity) { ex, ey := ent.Pos() max := 0 best_dist := 10000 var bx, by int var radius int if a.Range > 0 { radius += a.Range } if extra_dist > 0 { radius += extra_dist } for x := ex - radius; x <= ex+radius; x++ { for y := ey - radius; y <= ey+radius; y++ { if !ent.HasLos(x, y, 1, 1) { continue } targets = a.getTargetsAt(ent.Game(), x, y) ok := true count := 0 for i := range targets { if targets[i].Side() != ent.Side() { count++ } else if ent.Side() == game.SideHaunt && spec == AiAoeHitMinionsOk { if targets[i].HauntEnt == nil || targets[i].HauntEnt.Level != game.LevelMinion { ok = false } } else if spec != AiAoeHitAlliesOk { ok = false } } dx := x - ex if dx < 0 { dx = -dx } dy := y - ey if dy < 0 { dy = -dy } dist := dx if dy > dx { dist = dy } if ok && (count > max || count == max && dist < best_dist) { max = count best_dist = dist bx, by = x, y } } } return bx, by, a.getTargetsAt(ent.Game(), bx, by) }
func rangedDistBetween(e1, e2 *game.Entity) int { e1x, e1y := e1.Pos() e2x, e2y := e2.Pos() dx := e1x - e2x dy := e1y - e2y if dx < 0 { dx = -dx } if dy < 0 { dy = -dy } if dx > dy { return dx } return dy }
func (a *Interact) findDoors(ent *game.Entity, g *game.Game) []*house.Door { room_num := ent.CurrentRoom() room := g.House.Floors[0].Rooms[room_num] x, y := ent.Pos() dx, dy := ent.Dims() ent_rect := makeIntFrect(x, y, x+dx, y+dy) var valid []*house.Door for _, door := range room.Doors { if door.AlwaysOpen() { continue } if ent_rect.Overlaps(makeRectForDoor(room, door)) { valid = append(valid, door) } } return valid }
func (a *Interact) AiInteractWithObject(ent, object *game.Entity) game.ActionExec { if ent.Stats.ApCur() < a.Ap { return nil } if distBetweenEnts(ent, object) > a.Range { return nil } x, y := object.Pos() dx, dy := object.Dims() if !ent.HasLos(x, y, dx, dy) { return nil } var exec interactExec exec.SetBasicData(ent, a) exec.Target = object.Id return &exec }
func (exec *moveExec) measureCost(ent *game.Entity, g *game.Game) int { if len(exec.Path) == 0 { base.Error().Printf("Zero length path") return -1 } if g.ToVertex(ent.Pos()) != exec.Path[0] { base.Error().Printf("Path doesn't begin at ent's position, %d != %d", g.ToVertex(ent.Pos()), exec.Path[0]) return -1 } graph := g.Graph(ent.Side(), true, nil) v := g.ToVertex(ent.Pos()) cost := 0 for _, step := range exec.Path[1:] { dsts, costs := graph.Adjacent(v) ok := false prev := v base.Log().Printf("Adj(%d):", v) for j := range dsts { base.Log().Printf("Node %d", dsts[j]) if dsts[j] == step { cost += int(costs[j]) v = dsts[j] ok = true break } } base.Log().Printf("%d -> %d: %t", prev, v, ok) if !ok { return -1 } } return cost }