mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 10:04:21 +03:00
448 lines
62 KiB
HTML
448 lines
62 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>MapRouteFinding</title>
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body>
|
|
<nav role="navigation">
|
|
<h1><a href="../index.html">
|
|
<img src="../docs-src/Figures/Inform.png" height=72">
|
|
</a></h1>
|
|
<ul><li><a href="../compiler.html">compiler tools</a></li>
|
|
<li><a href="../other.html">other tools</a></li>
|
|
<li><a href="../extensions.html">extensions and kits</a></li>
|
|
<li><a href="../units.html">unit test tools</a></li>
|
|
</ul><h2>Extensions</h2><ul>
|
|
<li><a href="../basic_inform/index.html">basic_inform</a></li>
|
|
<li><a href="../standard_rules/index.html">standard_rules</a></li>
|
|
</ul><h2>Kits</h2><ul>
|
|
<li><a href="../BasicInformKit/index.html">BasicInformKit</a></li>
|
|
<li><a href="../BasicInformExtrasKit/index.html">BasicInformExtrasKit</a></li>
|
|
<li><a href="../CommandParserKit/index.html">CommandParserKit</a></li>
|
|
<li><a href="../EnglishLanguageKit/index.html">EnglishLanguageKit</a></li>
|
|
<li><a href="index.html"><span class="selectedlink">WorldModelKit</span></a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of 'MapRouteFinding' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../extensions.html">Kits</a></li><li><a href="index.html">WorldModelKit</a></li><li><b>MapRouteFinding</b></li></ul><p class="purpose">Testing and changing the fundamental spatial relations.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Map Route-Finding</a></li><li><a href="#SP2">§2. Cache Control</a></li><li><a href="#SP3">§3. Fast Route-Finding</a></li><li><a href="#SP4">§4. Slow Route-Finding</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Map Route-Finding. </b>The general problem we have to solve here is: given \(x, y\in R\), where \(R\)
|
|
is the set of rooms and we write \(x\sim y\) if there is a map connection from
|
|
\(x\) to \(y\),
|
|
</p>
|
|
|
|
<ul class="items"><li>(i) find the smallest \(m\) such that there exist \(x = r_1\sim r_2\sim ...\sim r_m = y\in R\),
|
|
or determine that no such \(m\) exists, and
|
|
</li><li>(ii) find \(d\), the first direction to take from \(x\) to lead to \(r_2\), or
|
|
set \(d=0\) if no such path exists or if \(m=1\) so that \(x=y\).
|
|
</li></ul>
|
|
<p class="inwebparagraph">Thus a typical outcome might be either "a shortest path from the Town Square
|
|
to the Hilltop takes 11 moves, starting by going northeast from the Town
|
|
Square", or alternatively "there's no path from the Town Square to the
|
|
Hilltop at all". Note that the length of the shortest path is unambiguous,
|
|
but that there might be many alternative paths of this minimum length:
|
|
we deliberately do not specify which path is chosen if so, and the two
|
|
algorithms used below do not necessarily choose the same one.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Route-finding is not an easy operation in computation terms: the various
|
|
algorithms available have theoretical running times which are easy (if
|
|
sobering) to compute, but which are not in practice typical of what will
|
|
happen, because they are quite sensitive to the map in question. Are all
|
|
the rooms laid out in a long line? Are there clusters of connected rooms
|
|
like islands? Are there dense clumps of interconnecting rooms? Are there
|
|
huge but possibly time-saving loops? And so on. Overhead is also
|
|
important. We present a choice of two algorithms: the "fast" one
|
|
has a theoretical running time of \(O(n^3)\), where \(n\) is the number
|
|
of rooms, whereas the "slow" one runs in \(O(n^2)\), yet in practice
|
|
the fast one easily outperforms the slow on typical heavy-use cases with
|
|
large maps.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The other issue is memory usage: we essentially have to strike a bargain
|
|
between speed and memory overhead. Our "slow" algorithm needs only
|
|
\(O(n)\) storage, whereas our "fast" algorithm needs \(O(n^2)\), and this
|
|
is very significant in the Z-machine where array space is in desperately
|
|
short supply and where, if \(n > 50\) or so, the user is already likely to
|
|
be fighting for the last few bytes in readable memory.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The user is therefore offered the choice, by selecting the use options
|
|
"Use fast route-finding" and "Use slow route-finding": and the defaults,
|
|
if neither option is explicitly set, are fast on Glulx and slow on the
|
|
Z-machine. If both use options are explicitly set — which might happen
|
|
due to a disagreement between extensions — "fast" wins.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">SLOW_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">TARGET_GLULX</span><span class="plain">;</span>
|
|
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">ifnot</span><span class="plain">;</span>
|
|
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">SLOW_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. Cache Control. </b>We provide code to enable our route-finding algorithms to cache their partial
|
|
results from one usage to the next (though at present only the "fast"
|
|
algorithm does this). The difficulty here is that the result of a route
|
|
search depends on three things, any of which may change:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) which subset of rooms we are route-finding through;
|
|
</li><li>(b) which subset of doors we are allowing ourselves to use; and
|
|
</li><li>(c) the current map connections between rooms.
|
|
</li></ul>
|
|
<p class="inwebparagraph">We keep track of (c) by watching for calls to <code class="display"><span class="extract">SignalMapChange()</span></code> from the
|
|
routines in "WorldModel.i6t" which alter the map. (a) and (b), however,
|
|
require tracking from call to call what the current subset of rooms and
|
|
doors is. (It is not sufficient to remember the criteria used last time
|
|
and this time, because circumstances could have changed such that the
|
|
criteria produce a different outcome. For instance, searching through
|
|
lighted rooms and using unlocked doors will produce a different result
|
|
if a door has been locked or unlocked since last time, or if a room has
|
|
become lighted or not.) We store the set of applicable rooms and doors
|
|
by enumerating them in the property <code class="display"><span class="extract">room_index</span></code> and by the flags in the
|
|
<code class="display"><span class="extract">DoorRoutingViable</span></code> array respectively.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">NUM_DOORS</span><span class="plain"> = </span><span class="identifier">ICOUNT_DOOR</span><span class="plain">;</span>
|
|
<span class="reserved">Constant</span><span class="plain"> </span><span class="identifier">NUM_ROOMS</span><span class="plain"> = </span><span class="identifier">ICOUNT_ROOM</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">Array</span><span class="plain"> </span><span class="identifier">DoorRoutingViable</span><span class="plain"> -> </span><span class="identifier">NUM_DOORS</span><span class="plain">+1;</span>
|
|
|
|
<span class="identifier">Global</span><span class="plain"> </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="identifier">Global</span><span class="plain"> </span><span class="identifier">last_filter</span><span class="plain">; </span><span class="identifier">Global</span><span class="plain"> </span><span class="identifier">last_use_doors</span><span class="plain">;</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">SignalMapChange</span><span class="plain">; </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">; ];</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">MapRouteTo</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">to</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">count</span><span class="plain"> </span><span class="identifier">oy</span><span class="plain"> </span><span class="identifier">oyi</span><span class="plain"> </span><span class="identifier">ds</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="reserved">to</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain">) && (</span><span class="identifier">filter</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain">) && (</span><span class="identifier">filter</span><span class="plain">(</span><span class="reserved">to</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">last_filter</span><span class="plain"> ~= </span><span class="identifier">filter</span><span class="plain">) || (</span><span class="identifier">last_use_doors</span><span class="plain"> ~= </span><span class="identifier">use_doors</span><span class="plain">)) </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="identifier">oyi</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">filter</span><span class="plain">(</span><span class="identifier">oy</span><span class="plain">))) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> == -1) </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> = </span><span class="identifier">oyi</span><span class="plain">++;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">oyi</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">ofclass</span><span class="plain"> </span><span class="identifier">K4_door</span><span class="plain">) {</span>
|
|
<span class="identifier">ds</span><span class="plain"> = </span><span class="reserved">false</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">use_doors</span><span class="plain"> & </span><span class="constant">2</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">open</span><span class="plain">) || ((</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">openable</span><span class="plain">) && (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">hasnt</span><span class="plain"> </span><span class="identifier">locked</span><span class="plain">))) </span><span class="identifier">ds</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">DoorRoutingViable</span><span class="plain">-></span><span class="identifier">oyi</span><span class="plain"> ~= </span><span class="identifier">ds</span><span class="plain">) </span><span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="identifier">DoorRoutingViable</span><span class="plain">-></span><span class="identifier">oyi</span><span class="plain"> = </span><span class="identifier">ds</span><span class="plain">;</span>
|
|
<span class="identifier">oyi</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">map_has_changed</span><span class="plain">) {</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">; </span><span class="identifier">ComputeFWMatrix</span><span class="plain">(</span><span class="identifier">filter</span><span class="plain">, </span><span class="identifier">use_doors</span><span class="plain">); #</span><span class="identifier">endif</span><span class="plain">;</span>
|
|
<span class="identifier">map_has_changed</span><span class="plain"> = </span><span class="reserved">false</span><span class="plain">; </span><span class="identifier">last_filter</span><span class="plain"> = </span><span class="identifier">filter</span><span class="plain">; </span><span class="identifier">last_use_doors</span><span class="plain"> = </span><span class="identifier">use_doors</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FastCountRouteTo</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">to</span><span class="plain">, </span><span class="identifier">filter</span><span class="plain">, </span><span class="identifier">use_doors</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FastRouteTo</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">to</span><span class="plain">, </span><span class="identifier">filter</span><span class="plain">, </span><span class="identifier">use_doors</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifnot</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SlowCountRouteTo</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">to</span><span class="plain">, </span><span class="identifier">filter</span><span class="plain">, </span><span class="identifier">use_doors</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">SlowRouteTo</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">to</span><span class="plain">, </span><span class="identifier">filter</span><span class="plain">, </span><span class="identifier">use_doors</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span><span class="plain">;</span>
|
|
<span class="plain">];</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. Fast Route-Finding. </b>The following is a form of Floyd's adaptation of Warshall's algorithm for
|
|
finding the transitive closure of a directed graph.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We need to store a matrix which for each pair of rooms \(R_i\) and \(R_j\)
|
|
records \(a_{ij}\), the shortest path length from \(R_i\) to \(R_j\) or 0 if no
|
|
path exists, and also \(d_{ij}\), the first direction to take on leaving
|
|
\(R_i\) along a shortest path to \(R_j\), or 0 if no path exists. For the sake
|
|
of economy we represent the directions as their instance counts (numbered
|
|
from 0 in order of creation), not as their direction object values, and
|
|
then store a single word for each pair \((i, j)\): we store \(d_{ij} + D
|
|
a_{ij}\(. This restricts us on a signed 16-bit virtual machine, and with the
|
|
conventional set of \(D=12\) directions, to the range \(0\leq a_{ij}\leq
|
|
5461\(, that is, to path lengths of 5461 steps or fewer. A work of IF with
|
|
5461 rooms will not fit in the Z-machine anyway: such a work would be on
|
|
Glulx, which is 32-bit, and where \(0\leq a_{ij}\leq 357,913,941\).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We begin with \(a_{ij} = 0\) for all pairs except where there is a viable
|
|
map connection between \(R_i\) and \(R_j\): for those we set \(a_{ij}=1\) and
|
|
\(d_{ij}\) equal to the direction of that map connection.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Following Floyd and Warshall we test if each known shortest path \(R_{x}\) to
|
|
\(R_{y}\) can be used to shorten the best known path from \(R_{x}\) to anywhere
|
|
else: that is, we look for cases where \(a_{xy} + a_{yj} < a_{xj}\), since
|
|
those show that going from \(R_x\) to \(R_j\) via \(R_y\) takes fewer steps than
|
|
going directly. See for instance Robert Sedgewick, {\it Algorithms} (1988),
|
|
chapter 32.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The trouble with the Floyd-Warshall algorithm is not so much that it takes
|
|
in principle \(O(n^3)\) time to construct the matrix: it does, but the
|
|
coefficient is low, and in the early stages of the outer loop the fact that
|
|
the vertex degree is at most \(D\) and usually much lower helps to reduce the
|
|
work further. The trouble is that there is no way to compute only the part
|
|
of the matrix we want: we have to have the entire thing, and that means
|
|
storing \(n^2\) words of data, by which point we have computed not only the
|
|
fastest route from \(R_x\) to \(R_y\) but also the fastest route from anywhere
|
|
to anywhere else. Even when the original map is sparse, the Floyd-Warshall
|
|
matrix is not, and it is difficult to store in any very compressed way
|
|
without greatly increasing the complexity of the code. This is why we cache
|
|
the results: we might as well, since we had to build the entire memory
|
|
structure anyway, and it means the time expense is only paid once (or once
|
|
for every time the state of doors and map connections changes), and the
|
|
cache is useful for all future routes whatever their endpoints.
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="reserved">Array</span><span class="plain"> </span><span class="identifier">FWMatrix</span><span class="plain"> --> </span><span class="identifier">NUM_ROOMS</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain">;</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">FastRouteTo</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">to</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">diri</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain"> </span><span class="identifier">oy</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="identifier">i</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="reserved">to</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))/</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="identifier">diri</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="reserved">to</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))%</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="identifier">i</span><span class="plain">=0; </span><span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">dir</span><span class="plain"> </span><span class="reserved">ofclass</span><span class="plain"> </span><span class="identifier">K3_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> == </span><span class="identifier">diri</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain">;</span>
|
|
<span class="identifier">i</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">FastCountRouteTo</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">to</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="identifier">k</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="reserved">to</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))/</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">ComputeFWMatrix</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">oy</span><span class="plain"> </span><span class="identifier">ox</span><span class="plain"> </span><span class="identifier">oj</span><span class="plain"> </span><span class="identifier">axy</span><span class="plain"> </span><span class="identifier">ayj</span><span class="plain"> </span><span class="identifier">axj</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain"> </span><span class="identifier">diri</span><span class="plain"> </span><span class="identifier">nd</span><span class="plain"> </span><span class="identifier">row</span><span class="plain">;</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">ox</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">) = </span><span class="constant">0</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="identifier">row</span><span class="plain"> = (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">IK1_Count</span><span class="plain">)*</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">diri</span><span class="plain">=0: </span><span class="identifier">diri</span><span class="plain"><</span><span class="identifier">No_Directions</span><span class="plain">: </span><span class="identifier">diri</span><span class="plain">++) {</span>
|
|
<span class="identifier">ox</span><span class="plain"> = </span><span class="identifier">Map_Storage</span><span class="plain">-->(</span><span class="identifier">row</span><span class="plain">+</span><span class="identifier">diri</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ox</span><span class="plain">) && (</span><span class="identifier">ox</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) && (</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">)) {</span>
|
|
<span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">) = </span><span class="identifier">No_Directions</span><span class="plain"> + </span><span class="identifier">diri</span><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">use_doors</span><span class="plain"> && (</span><span class="identifier">ox</span><span class="plain"> </span><span class="reserved">ofclass</span><span class="plain"> </span><span class="identifier">K4_door</span><span class="plain">) &&</span>
|
|
<span class="plain">((</span><span class="identifier">use_doors</span><span class="plain"> & </span><span class="constant">2</span><span class="plain">) || (</span><span class="identifier">DoorRoutingViable</span><span class="plain">->(</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">IK4_Count</span><span class="plain">)))) {</span>
|
|
<span class="plain">@</span><span class="identifier">push</span><span class="plain"> </span><span class="identifier">location</span><span class="plain">; </span><span class="identifier">location</span><span class="plain"> = </span><span class="identifier">oy</span><span class="plain">;</span>
|
|
<span class="identifier">ox</span><span class="plain"> = </span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">door_to</span><span class="plain">();</span>
|
|
<span class="plain">@</span><span class="identifier">pull</span><span class="plain"> </span><span class="identifier">location</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ox</span><span class="plain">) && (</span><span class="identifier">ox</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) && (</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">)) {</span>
|
|
<span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">) = </span><span class="identifier">No_Directions</span><span class="plain"> + </span><span class="identifier">diri</span><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">ox</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="identifier">axy</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))/</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">axy</span><span class="plain"> > </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">oj</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">oj</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain"> >= </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="identifier">ayj</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">oj</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))/</span><span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ayj</span><span class="plain"> > </span><span class="constant">0</span><span class="plain">) {</span>
|
|
<span class="comment">rint "Is it faster to go from ", (name) ox, " to ",</span>
|
|
<span class="comment"> (name) oj, " via ", (name) oy, "?^";</span>
|
|
<span class="identifier">axj</span><span class="plain"> = (</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">oj</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))/</span>
|
|
<span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">axj</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">axy</span><span class="plain"> + </span><span class="identifier">ayj</span><span class="plain"> < </span><span class="identifier">axj</span><span class="plain">)) {</span>
|
|
<span class="comment">rint "Yes^";</span>
|
|
<span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">oj</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">) =</span>
|
|
<span class="plain">(</span><span class="identifier">axy</span><span class="plain"> + </span><span class="identifier">ayj</span><span class="plain">)*</span><span class="identifier">No_Directions</span><span class="plain"> +</span>
|
|
<span class="plain">(</span><span class="identifier">FWMatrix</span><span class="plain">-->(</span><span class="identifier">ox</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">*</span><span class="identifier">NUM_ROOMS</span><span class="plain"> + </span><span class="identifier">oy</span><span class="plain">.</span><span class="identifier">room_index</span><span class="plain">))%</span>
|
|
<span class="identifier">No_Directions</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">#</span><span class="identifier">ENDIF</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Slow Route-Finding. </b>The alternative algorithm, used when only \(O(n)\) memory is available,
|
|
computes only some of the shortest paths leading to \(R_y\), and is not cached —
|
|
both because the storage is likely to be reused often by other searches and
|
|
because there is little gain from doing so, given that a subsequent search
|
|
with different endpoints will not benefit from the results of this one. On
|
|
the other hand, to call it "slow" is a little unfair. It is somewhat like
|
|
Prim's algorithm for finding a minimum spanning tree, rooted at \(R_y\), and
|
|
grows the tree outward from \(R_y\) until either \(R_x\) is reached — in which
|
|
case we stop immediately — or the (directed) component containing \(R_y\)
|
|
has been exhausted — in which case \(R_x\), which must lie outside this, can
|
|
have no path to \(R_y\). In principle, the running time is \(O(dn^2)\), where
|
|
\(d\leq D\) is the maximum vertex degree and \(n\) is the number of rooms in
|
|
the component containing \(R_y\): in practice the degree is often much less
|
|
than 12, while the algorithm finishes quickly in cases where \(R_y\) is
|
|
relatively isolated and inaccessible or where a shortish route does exist,
|
|
and those are very common cases in typical usage. There will be circumstances
|
|
where, because few routes need to be found and because of the shape of the
|
|
map, the "slow" algorithm will outperform the "fast" one: this is why
|
|
the user is allowed to control which algorithm is used.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For each room \(R_z\), the property <code class="display"><span class="extract">vector</span></code> stores the direction object of
|
|
the way to go to its parent room in the tree rooted at \(R_y\). Thus if the
|
|
algorithm succeeds in finding a route from \(R_x\) to \(R_y\) then we generate
|
|
the route by starting at \(R_x\) and repeatedly going in the <code class="display"><span class="extract">vector</span></code> direction
|
|
from where we currently stand until we reach \(R_y\). Since every room needs
|
|
a <code class="display"><span class="extract">vector</span></code> value, this requires \(n\) words of storage. (The <code class="display"><span class="extract">vector</span></code> values
|
|
store only enough of the minimal spanning tree to go upwards through the
|
|
tree, but that's the only way we need to traverse it.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The method can be summed up thus:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) Begin with every vector blank except that of \(R_y\), the destination.
|
|
</li><li>(b) Repeatedly: For every room in the domain set, try each direction: if this
|
|
leads to a room whose vector was determined on the last round ({\it not} on
|
|
this one, as that may be a suboptimal route), set the vector to point to that
|
|
room.
|
|
</li><li>(c) Stop as soon as the vector from the origin is set, or when a round happens
|
|
in which no further vectors are found: in which case, we have completely
|
|
explored the component of the map from which the destination can be reached,
|
|
and the origin isn't in it, so we can return "no".
|
|
</li></ul>
|
|
<p class="inwebparagraph">To prove the correctness of this, we show inductively that after round \(n\)
|
|
we have set the <code class="display"><span class="extract">vector</span></code> for every room having a shortest path to \(R_y\) of
|
|
length \(n\), and that every <code class="display"><span class="extract">vector</span></code> points to a room having a <code class="display"><span class="extract">vector</span></code> in
|
|
the direction of the shortest path from there to \(R_y\).
|
|
</p>
|
|
|
|
<pre class="display">
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">FAST_ROUTE_FINDING</span><span class="plain">;</span>
|
|
<span class="plain">[ </span><span class="identifier">SlowRouteTo</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">to</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">obj</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain"> </span><span class="identifier">in_direction</span><span class="plain"> </span><span class="identifier">progressed</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain"> </span><span class="identifier">through_door</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="reserved">to</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="reserved">nothing</span><span class="plain">;</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">obj</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">to</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
|
|
<span class="comment">rint "Routing from ", (the) from, " to ", (the) to, "^";</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="reserved">true</span><span class="plain">) {</span>
|
|
<span class="identifier">progressed</span><span class="plain"> = </span><span class="reserved">false</span><span class="plain">;</span>
|
|
<span class="comment">rint "Pass begins^";</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">obj</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">filter</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">filter</span><span class="plain">(</span><span class="identifier">obj</span><span class="plain">)))</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">dir</span><span class="plain"> </span><span class="reserved">ofclass</span><span class="plain"> </span><span class="identifier">K3_direction</span><span class="plain">) {</span>
|
|
<span class="identifier">in_direction</span><span class="plain"> = </span><span class="identifier">Map_Storage</span><span class="plain">-->((</span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">IK1_Count</span><span class="plain">)*</span><span class="identifier">No_Directions</span><span class="plain"> + </span><span class="identifier">dir</span><span class="plain">.</span><span class="identifier">IK3_Count</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in_direction</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="comment">rint (the) obj, " > ", (the) dir, " > ", (the) in_direction, "^";</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">in_direction</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">in_direction</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">in_direction</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> > </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="plain">&& ((</span><span class="identifier">filter</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">filter</span><span class="plain">(</span><span class="identifier">in_direction</span><span class="plain">)))) {</span>
|
|
<span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> = </span><span class="identifier">dir</span><span class="plain"> | </span><span class="identifier">WORD_HIGHBIT</span><span class="plain">;</span>
|
|
<span class="comment">rint "* ", (the) obj, " vector is ", (the) dir, "^";</span>
|
|
<span class="identifier">progressed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">use_doors</span><span class="plain"> && (</span><span class="identifier">in_direction</span><span class="plain"> </span><span class="reserved">ofclass</span><span class="plain"> </span><span class="identifier">K4_door</span><span class="plain">) &&</span>
|
|
<span class="plain">((</span><span class="identifier">use_doors</span><span class="plain"> & </span><span class="constant">2</span><span class="plain">) ||</span>
|
|
<span class="plain"> (</span><span class="identifier">in_direction</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">open</span><span class="plain">) ||</span>
|
|
<span class="plain"> ((</span><span class="identifier">in_direction</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">openable</span><span class="plain">) && (</span><span class="identifier">in_direction</span><span class="plain"> </span><span class="reserved">hasnt</span><span class="plain"> </span><span class="identifier">locked</span><span class="plain">)))) {</span>
|
|
<span class="identifier">sl</span><span class="plain"> = </span><span class="identifier">location</span><span class="plain">; </span><span class="identifier">location</span><span class="plain"> = </span><span class="identifier">obj</span><span class="plain">;</span>
|
|
<span class="identifier">through_door</span><span class="plain"> = </span><span class="identifier">in_direction</span><span class="plain">.</span><span class="identifier">door_to</span><span class="plain">();</span>
|
|
<span class="identifier">location</span><span class="plain"> = </span><span class="identifier">sl</span><span class="plain">;</span>
|
|
<span class="comment">rint "Through door is ", (the) through_door, "^";</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">through_door</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">through_door</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">)</span>
|
|
<span class="plain">&& (</span><span class="identifier">through_door</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> > </span><span class="constant">0</span><span class="plain">)</span>
|
|
<span class="plain">&& ((</span><span class="identifier">filter</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">filter</span><span class="plain">(</span><span class="identifier">through_door</span><span class="plain">)))) {</span>
|
|
<span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> = </span><span class="identifier">dir</span><span class="plain"> | </span><span class="identifier">WORD_HIGHBIT</span><span class="plain">;</span>
|
|
<span class="comment">rint "* ", (the) obj, " vector is ", (the) dir, "^";</span>
|
|
<span class="identifier">progressed</span><span class="plain"> = </span><span class="reserved">true</span><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">objectloop</span><span class="plain"> (</span><span class="identifier">obj</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) </span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> = </span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain"> &~ </span><span class="identifier">WORD_HIGHBIT</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">progressed</span><span class="plain"> == </span><span class="reserved">false</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">];</span>
|
|
|
|
<span class="plain">[ </span><span class="identifier">SlowCountRouteTo</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">to</span><span class="plain"> </span><span class="identifier">filter</span><span class="plain"> </span><span class="identifier">use_doors</span><span class="plain"> </span><span class="identifier">obj</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="reserved">to</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="reserved">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain"> && </span><span class="reserved">to</span><span class="plain"> </span><span class="reserved">has</span><span class="plain"> </span><span class="identifier">mark_as_room</span><span class="plain">) {</span>
|
|
<span class="identifier">obj</span><span class="plain"> = </span><span class="identifier">MapRouteTo</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">,</span><span class="reserved">to</span><span class="plain">,</span><span class="identifier">filter</span><span class="plain">,</span><span class="identifier">use_doors</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">obj</span><span class="plain"> == </span><span class="reserved">nothing</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">obj</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
|
|
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">obj</span><span class="plain"> ~= </span><span class="reserved">to</span><span class="plain">) && (</span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">NUM_ROOMS</span><span class="plain">)) { </span><span class="identifier">i</span><span class="plain">++; </span><span class="identifier">obj</span><span class="plain"> = </span><span class="identifier">MapConnection</span><span class="plain">(</span><span class="identifier">obj</span><span class="plain">,</span><span class="identifier">obj</span><span class="plain">.</span><span class="identifier">vector</span><span class="plain">); }</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> -1;</span>
|
|
<span class="plain">];</span>
|
|
<span class="plain">#</span><span class="identifier">ENDIF</span><span class="plain">;</span>
|
|
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="S-wrl.html">Back to 'WorldModel Template'</a></li><li><a href="S-rtp.html">Continue with 'RTP Template'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
<script>
|
|
MathJax = {
|
|
tex: {
|
|
inlineMath: '$', '$'], ['\\(', '\\)'
|
|
},
|
|
svg: {
|
|
fontCache: 'global'
|
|
}
|
|
};
|
|
</script>
|
|
<script type="text/javascript" id="MathJax-script" async
|
|
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
|
|
</script>
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|