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 }
// Returns a list of rooms representing a path from src to dst. The path will // not include src, but will include dst. This function will return nil if // the path requires going through more than a single unexplored room, this // means that you can use this to path to an unexplored room, but you cannot // use it to path to a room further in the house than that. // rooms. // Format // path = roomPath(src, dst) // // Input: // src - Room to start the path from. // dst - Room to end the path at. // // Output: // path - array - A list of rooms that connect src to dst, excluding src // but including dst. func RoomPathFunc(a *Ai) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "roomPath", game.LuaRoom, game.LuaRoom) { return 0 } me := a.ent g := me.Game() graph := g.RoomGraph() r1 := game.LuaToRoom(L, g, -2) r2 := game.LuaToRoom(L, g, -1) if r1 == nil || r2 == nil { game.LuaDoError(L, fmt.Sprintf("Referenced one or more invalid rooms.")) return 0 } L.PushString("room") L.GetTable(-3) r1_index := L.ToInteger(-1) L.Pop(1) L.PushString("room") L.GetTable(-2) r2_index := L.ToInteger(-1) L.Pop(1) cost, path := algorithm.Dijkstra(graph, []int{r1_index}, []int{r2_index}) if cost == -1 { L.PushNil() return 1 } num_unexplored := 0 for _, v := range path { if !me.Info.RoomsExplored[v] { num_unexplored++ } } if num_unexplored > 1 { L.PushNil() return 1 } L.NewTable() for i, v := range path { if i == 0 { continue } // Skip this one because we're in it already L.PushInteger(i) game.LuaPushRoom(L, g, g.House.Floors[0].Rooms[v]) L.SetTable(-3) } return 1 } }
func DijkstraSpec(c gospec.Context) { b := [][]int{ []int{1, 2, 9, 4, 3, 2, 1}, // 0 - 6 []int{9, 2, 9, 4, 3, 1, 1}, // 7 - 13 []int{2, 1, 5, 5, 5, 2, 1}, // 14 - 20 []int{1, 1, 1, 1, 1, 1, 1}, // 21 - 27 } c.Specify("Check Dijkstra's gives the right path and weight", func() { weight, path := algorithm.Dijkstra(board(b), []int{0}, []int{11}) c.Expect(weight, Equals, 16.0) c.Expect(path, ContainsInOrder, []int{0, 1, 8, 15, 22, 23, 24, 25, 26, 19, 12, 11}) }) c.Specify("Check multiple sources", func() { weight, path := algorithm.Dijkstra(board(b), []int{0, 1, 7, 2}, []int{11}) c.Expect(weight, Equals, 10.0) c.Expect(path, ContainsInOrder, []int{2, 3, 4, 11}) }) c.Specify("Check multiple destinations", func() { weight, path := algorithm.Dijkstra(board(b), []int{0}, []int{6, 11, 21}) c.Expect(weight, Equals, 7.0) c.Expect(path, ContainsInOrder, []int{0, 1, 8, 15, 22, 21}) }) }
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) } }
// If this returns a path with length 0 it means there wasn't a valid path func (s *Sprite) findPathForCmd(cmd command, anim_node *yed.Node) []*yed.Node { var node_path []*yed.Node for _, name := range cmd.names { g := pathingGraph{shared: s.shared, start: anim_node, cmd: name} var end []int for i := 0; i < s.shared.anim.NumEdges(); i++ { edge := s.shared.anim.Edge(i) if s.shared.edge_data[edge].cmd == name { end = append(end, edge.Dst().Id()) } } _, path := algorithm.Dijkstra(g, []int{s.shared.anim.NumNodes()}, end) for _, id := range path[1:] { node_path = append(node_path, s.shared.anim.Node(id)) } if len(node_path) > 0 { anim_node = node_path[len(node_path)-1] } } return node_path }