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 }
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 WaypointsFunc(me *game.Entity) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "Waypoints") { return 0 } g := me.Game() L.NewTable() count := 0 for _, wp := range g.Waypoints { if wp.Side != me.Side() { continue } count++ L.PushInteger(count) L.NewTable() L.PushString("Name") L.PushString(wp.Name) L.SetTable(-3) L.PushString("Radius") L.PushNumber(wp.Radius) L.SetTable(-3) L.PushString("Pos") game.LuaPushPoint(L, int(wp.X), int(wp.Y)) L.SetTable(-3) L.SetTable(-3) } return 1 } }
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 (a *Move) findPath(ent *game.Entity, x, y int) { g := ent.Game() dst := g.ToVertex(x, y) if dst != a.dst || !a.calculated { a.dst = dst a.calculated = true src := g.ToVertex(a.ent.Pos()) graph := g.Graph(ent.Side(), true, nil) cost, path := algorithm.Dijkstra(graph, []int{src}, []int{dst}) if len(path) <= 1 { return } a.path = algorithm.Map(path, [][2]int{}, func(a interface{}) interface{} { _, x, y := g.FromVertex(a.(int)) return [2]int{int(x), int(y)} }).([][2]int) a.cost = int(cost) if path_tex != nil { pix := path_tex.Pix() for i := range pix { for j := range pix[i] { pix[i][j] = 0 } } current := 0.0 for i := 1; i < len(a.path); i++ { src := g.ToVertex(a.path[i-1][0], a.path[i-1][1]) dst := g.ToVertex(a.path[i][0], a.path[i][1]) v, cost := graph.Adjacent(src) for j := range v { if v[j] == dst { current += cost[j] break } } pix[a.path[i][1]][a.path[i][0]] += byte(current) } path_tex.Remap() } } }
func (a *Move) findPath(ent *game.Entity, x, y int) { g := ent.Game() dst := g.ToVertex(x, y) if dst != a.dst || !a.calculated { a.dst = dst a.calculated = true src := g.ToVertex(a.ent.Pos()) graph := g.Graph(ent.Side(), true, nil) cost, path := algorithm.Dijkstra(graph, []int{src}, []int{dst}) if len(path) <= 1 { return } a.path = algorithm.Map(path, [][2]int{}, func(a interface{}) interface{} { _, x, y := g.FromVertex(a.(int)) return [2]int{int(x), int(y)} }).([][2]int) a.cost = int(cost) a.drawPath(ent, g, graph, src) } }
func limitPath(ent *game.Entity, start int, path []int, max int) []int { total := 0 graph := ent.Game().Graph(ent.Side(), true, nil) for last := 1; last < len(path); last++ { adj, cost := graph.Adjacent(start) found := false for index := range adj { if adj[index] == path[last] { total += int(cost[index]) if total > max { return path[0:last] } start = adj[index] found = true break } } if !found { base.Log().Printf("PATH: DIdn't find, %d / %d", last+1, len(path)) return path[0:last] } } return path }