1 QuestHelper_File
["graph.lua"] = "Development Version"
3 local floor = math
.floor
5 local function Graph_Search(self
, first
, last
)
8 while #open
> 0 do table.remove(open
) end
9 for _
, n
in ipairs(self
.nodes
) do n
.s
= 0 end
11 table.insert(open
, first
)
17 local current
= table.remove(open
)
19 if current
== last
then
27 for n
, d
in pairs(current
.n
) do
29 -- Haven't visited this node yet.
35 local mn
, mx
= 1, #open
+1
38 local m
= floor((mn
+mx
)*0.5)
47 table.insert(open
, mn
, n
)
53 local mn
, mx
= 1, #open
56 local m
= floor((mn
+mx
)*0.5)
64 while open
[mn
] ~= n
do
68 table.remove(open
, mn
)
71 local m
= floor((mn
+mx
)*0.5)
80 table.insert(open
, mn
, n
)
90 local function sanity(list
, node
)
92 local contains
= false
93 for i
, n
in ipairs(list
) do
94 if not (not last
or last
>= n
.g
) then
95 for i
, n
in ipairs(list
) do
96 QuestHelper
:TextOut(i
..") "..n
.g
)
98 QuestHelper
:Error("Order "..i
.."/"..#list
.." ("..n
.g
..")")
100 assert(not last
or last
>= n
.g
)
106 if node
and not contains
then QuestHelper
:Error("Missing") end
109 local function Graph_Node_Link(self
, next_node
, distance
)
110 if type(distance
) ~= "number" or distance
< 0 then QuestHelper
:Error("Boom!") end
111 if self
~= next_node
then
112 self
.n
[next_node
] = distance
113 table.insert(next_node
.r
, self
)
117 local function Graph_CreateNode(self
)
118 local node
= QuestHelper
:CreateTable()
119 node
.Link
= Graph_Node_Link
120 node
.n
= QuestHelper
:CreateTable()
121 node
.r
= QuestHelper
:CreateTable()
122 table.insert(self
.nodes
, node
)
126 local function Graph_DestroyNode(self
, node
)
127 for i
= 1,#self
.nodes
do
128 if self
.nodes
[i
] == node
then
129 table.remove(self
.nodes
, i
)
130 QuestHelper
:ReleaseTable(node
.n
)
131 QuestHelper
:ReleaseTable(node
.r
)
132 QuestHelper
:ReleaseTable(node
)
138 local function Graph_Reset(self
)
139 while #self
.nodes
> 0 do
140 local node
= table.remove(self
.nodes
)
141 QuestHelper
:ReleaseTable(node
.n
)
142 QuestHelper
:ReleaseTable(node
.r
)
143 QuestHelper
:ReleaseTable(node
)
147 local function Graph_AddRouteStartNode(self
, n
, g
, end_list
)
148 local open
= self
.open
159 local mn
, mx
= 1, #open
162 local m
= floor((mn
+mx
)*0.5)
163 if open
[m
].g
> og
then
170 while open
[mn
] ~= n
do
174 table.remove(open
, mn
)
176 return -- Don't want to insert the node a second time.
180 local mn
, mx
= 1, #open
+1
183 local m
= floor((mn
+mx
)*0.5)
185 if open
[m
].g
> g
then
192 table.insert(open
, mn
, n
)
197 local function Graph_DoRouteSearch(self
, end_list
)
198 local open
= self
.open
199 local end_count
= #end_list
202 local current
= table.remove(open
)
204 if current
.s
== 3 or current
.s
== 4 then
213 for n
, d
in pairs(current
.n
) do
214 if n
.s
== 0 or n
.s
== 3 then
215 -- Haven't visited this node yet.
220 n
.s
= n
.s
== 3 and 4 or 1
222 local mn
, mx
= 1, #open
+1
225 local m
= floor((mn
+mx
)*0.5)
227 if open
[m
].g
> g
then
234 table.insert(open
, mn
, n
)
235 elseif n
.s
== 1 or n
.s
== 4 then
241 local mn
, mx
= 1, #open
244 local m
= floor((mn
+mx
)*0.5)
245 if open
[m
].g
> og
then
252 while open
[mn
] ~= n
do
258 table.remove(open
, mn
)
261 local m
= floor((mn
+mx
)*0.5)
263 if open
[m
].g
> g
then
271 table.insert(open
, mn
, n
)
278 local function Graph_PrepareSearch(self
)
279 local open
= self
.open
280 for n
in pairs(open
) do open
[n
] = nil end
281 for _
, n
in pairs(self
.nodes
) do
286 local function Graph_AddStartNode(self
, n
, g
, end_list
)
287 local open
= self
.open
298 local mn
, mx
= 1, #open
301 local m
= floor((mn
+mx
)*0.5)
302 if open
[m
].g
> og
then
309 while open
[mn
] ~= n
do
313 table.remove(open
, mn
)
315 return -- Don't want to insert the node a second time.
319 local mn
, mx
= 1, #open
+1
322 local m
= floor((mn
+mx
)*0.5)
324 if open
[m
].g
> g
then
331 table.insert(open
, mn
, n
)
336 local function Graph_DoSearch(self
, end_list
)
337 local open
= self
.open
338 local end_count
= #end_list
341 local current
= table.remove(open
)
343 if current
.s
== 3 or current
.s
== 4 then
352 for n
, d
in pairs(current
.n
) do
353 if n
.s
== 0 or n
.s
== 3 then
354 -- Haven't visited this node yet.
359 n
.s
= n
.s
== 3 and 4 or 1
361 local mn
, mx
= 1, #open
+1
364 local m
= floor((mn
+mx
)*0.5)
366 if open
[m
].g
> g
then
373 table.insert(open
, mn
, n
)
374 elseif n
.s
== 1 or n
.s
== 4 then
380 local mn
, mx
= 1, #open
383 local m
= floor((mn
+mx
)*0.5)
384 if open
[m
].g
> og
then
391 while open
[mn
] ~= n
do
397 table.remove(open
, mn
)
400 local m
= floor((mn
+mx
)*0.5)
402 if open
[m
].g
> g
then
410 table.insert(open
, mn
, n
)
419 local function Graph_DoFullSearch(self
, end_list
)
420 local open
= self
.open
421 local end_count
= #end_list
424 local current
= table.remove(open
)
426 if current
.s
== 3 or current
.s
== 4 then
427 if end_count
== 1 then
428 for i
= 1,#removed
do
429 table.insert(end_list
, table.remove(removed
))
434 for i
= 1,end_count
do
435 if end_list
[i
] == current
then
436 table.insert(removed
, table.remove(end_list
, i
))
441 end_count
= end_count
- 1
448 for n
, d
in pairs(current
.n
) do
449 if n
.s
== 0 or n
.s
== 3 then
450 -- Haven't visited this node yet.
455 n
.s
= n
.s
== 3 and 4 or 1
457 local mn
, mx
= 1, #open
+1
460 local m
= floor((mn
+mx
)*0.5)
462 if open
[m
].g
> g
then
469 table.insert(open
, mn
, n
)
470 elseif n
.s
== 1 or n
.s
== 4 then
476 local mn
, mx
= 1, #open
479 local m
= floor((mn
+mx
)*0.5)
480 if open
[m
].g
> og
then
487 while open
[mn
] ~= n
do
493 table.remove(open
, mn
)
496 local m
= floor((mn
+mx
)*0.5)
498 if open
[m
].g
> g
then
506 table.insert(open
, mn
, n
)
512 for i
, n
in ipairs(end_list
) do
513 QuestHelper
:TextOut(i
..") Failed to reach: "..n
.name
..", s="..n
.s
)
516 for i
= 1,#removed
do
517 table.insert(end_list
, table.remove(removed
))
520 for i
, n
in ipairs(end_list
) do
521 QuestHelper
:TextOut(i
..") End node: "..n
.name
..", s="..n
.s
)
524 QuestHelper
:Error("Boom!")
526 for i
= 1,#removed
do
527 table.insert(end_list
, table.remove(removed
))
531 local function propLinks(node
)
534 for n
in pairs(node
.n
) do
540 function Graph_SanityCheck(self
)
541 for i
= 1,#self
.nodes
do
542 for _
, n
in ipairs(self
.nodes
) do
546 propLinks(self
.nodes
[i
])
548 for _
, n
in ipairs(self
.nodes
) do
550 QuestHelper
:TextOut((n
.name
or "unknown").." isn't reachable from "..(self
.nodes
[i
].name
or "unknown"))
556 function QuestHelper
:CreateGraph()
557 local graph
= self
:CreateTable()
558 graph
.nodes
= self
:CreateTable()
559 graph
.end_nodes
= self
:CreateTable()
560 graph
.open
= self
:CreateTable()
562 graph
.CreateNode
= Graph_CreateNode
563 graph
.DestroyNode
= Graph_DestroyNode
564 graph
.Reset
= Graph_Reset
566 graph
.PrepareSearch
= Graph_PrepareSearch
568 graph
.AddRouteStartNode
= Graph_AddRouteStartNode
569 graph
.DoRouteSearch
= Graph_DoRouteSearch
570 graph
.Search
= Graph_Search
571 graph
.SanityCheck
= Graph_SanityCheck
573 -- These don't deal with finding paths and instead only care about finding distances.
574 graph
.AddStartNode
= Graph_AddStartNode
575 graph
.DoSearch
= Graph_DoSearch
576 graph
.DoFullSearch
= Graph_DoFullSearch
581 function QuestHelper
:ReleaseGraph(graph
)
583 self
:ReleaseTable(graph
.nodes
)
584 self
:ReleaseTable(graph
.end_nodes
)
585 self
:ReleaseTable(graph
.open
)
586 self
:ReleaseTable(graph
)
589 QuestHelper
.world_graph
= QuestHelper
:CreateGraph()