FindPath returns the sequence of ExitName/RoomID steps from startRoom to goalRoom.
(startRoom, goalRoom int)
| 100 | |
| 101 | // FindPath returns the sequence of ExitName/RoomID steps from startRoom to goalRoom. |
| 102 | func (r *mapper) findPath(startRoom, goalRoom int) ([]pathStep, error) { |
| 103 | |
| 104 | if startRoom == goalRoom { |
| 105 | return nil, ErrPathDestMatch |
| 106 | } |
| 107 | |
| 108 | // sanity check |
| 109 | if _, ok := r.crawledRooms[startRoom]; !ok { |
| 110 | return nil, ErrRoomNotFound |
| 111 | } |
| 112 | if _, ok := r.crawledRooms[goalRoom]; !ok { |
| 113 | return nil, ErrRoomNotFound |
| 114 | } |
| 115 | |
| 116 | // cameFrom holds, for each room, how we got there. |
| 117 | cameFrom := make(map[int]prevInfo, len(r.crawledRooms)) |
| 118 | |
| 119 | // gScore: cost from start to here; fScore = gScore + heuristic |
| 120 | gScore := make(map[int]float64, len(r.crawledRooms)) |
| 121 | fScore := make(map[int]float64, len(r.crawledRooms)) |
| 122 | for id := range r.crawledRooms { |
| 123 | gScore[id] = math.Inf(1) |
| 124 | fScore[id] = math.Inf(1) |
| 125 | } |
| 126 | gScore[startRoom] = 0 |
| 127 | fScore[startRoom] = r.heuristic(startRoom, goalRoom) |
| 128 | |
| 129 | // open set as a priority queue |
| 130 | openSet := make(priorityQueue, 0, len(r.crawledRooms)) |
| 131 | heap.Init(&openSet) |
| 132 | heap.Push(&openSet, &nodeRecord{roomId: startRoom, fScore: fScore[startRoom]}) |
| 133 | inOpen := map[int]*nodeRecord{startRoom: openSet[0]} |
| 134 | |
| 135 | for openSet.Len() > 0 { |
| 136 | current := heap.Pop(&openSet).(*nodeRecord) |
| 137 | delete(inOpen, current.roomId) |
| 138 | |
| 139 | // reached goal! |
| 140 | if current.roomId == goalRoom { |
| 141 | // reconstruct path |
| 142 | var path []pathStep |
| 143 | cur := goalRoom |
| 144 | for cur != startRoom { |
| 145 | info := cameFrom[cur] |
| 146 | |
| 147 | // record the exit name and the room we arrived in |
| 148 | path = append(path, pathStep{exitName: info.viaExit, roomId: cur}) |
| 149 | cur = info.prevRoom |
| 150 | } |
| 151 | |
| 152 | pathLen := len(path) |
| 153 | |
| 154 | if pathLen > 0 { |
| 155 | // reverse |
| 156 | for i := 0; i < pathLen/2; i++ { |
| 157 | j := len(path) - 1 - i |
| 158 | path[i], path[j] = path[j], path[i] |
| 159 | } |