mirror of
https://github.com/ganelson/inform.git
synced 2024-07-16 22:14:23 +03:00
463 lines
77 KiB
HTML
463 lines
77 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>
|
|
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<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="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
<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>
|
|
|
|
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
|
|
</head>
|
|
<body class="commentary-font">
|
|
<nav role="navigation">
|
|
<h1><a href="../index.html">
|
|
<img src="../docs-assets/Inform.png" height=72">
|
|
</a></h1>
|
|
<ul><li><a href="../index.html">home</a></li>
|
|
</ul><h2>Compiler</h2><ul>
|
|
<li><a href="../structure.html">structure</a></li>
|
|
<li><a href="../inbuildn.html">inbuild</a></li>
|
|
<li><a href="../inform7n.html">inform7</a></li>
|
|
<li><a href="../intern.html">inter</a></li>
|
|
<li><a href="../services.html">services</a></li>
|
|
<li><a href="../secrets.html">secrets</a></li>
|
|
</ul><h2>Other Tools</h2><ul>
|
|
<li><a href="../inblorbn.html">inblorb</a></li>
|
|
<li><a href="../indocn.html">indoc</a></li>
|
|
<li><a href="../inform6.html">inform6</a></li>
|
|
<li><a href="../inpolicyn.html">inpolicy</a></li>
|
|
<li><a href="../inrtpsn.html">inrtps</a></li>
|
|
</ul><h2>Resources</h2><ul>
|
|
<li><a href="../extensions.html">extensions</a></li>
|
|
<li><a href="../kits.html">kits</a></li>
|
|
</ul><h2>Repository</h2><ul>
|
|
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
|
|
</ul><h2>Related Projects</h2><ul>
|
|
<li><a href="../../../inweb/index.html">inweb</a></li>
|
|
<li><a href="../../../intest/index.html">intest</a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
<main role="main">
|
|
<!--Weave of 'MapRouteFinding' generated by Inweb-->
|
|
<div class="breadcrumbs">
|
|
<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></div>
|
|
<p class="purpose">Testing and changing the fundamental spatial relations.</p>
|
|
|
|
<ul class="toc"><li><a href="S-mpr.html#SP1">§1. Map Route-Finding</a></li><li><a href="S-mpr.html#SP2">§2. Cache Control</a></li><li><a href="S-mpr.html#SP4">§4. Fast Route-Finding</a></li><li><a href="S-mpr.html#SP5">§5. Slow Route-Finding</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></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="commentary">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="commentary">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="commentary">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="commentary">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="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">UseFastRouteFinding</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WorldModelKit</span><span class="plain-syntax">`</span><span class="identifier-syntax">ROUTE_FINDING_CFGV</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">TARGET_ZCODE</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifnot</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WorldModelKit</span><span class="plain-syntax">`</span><span class="identifier-syntax">ROUTE_FINDING_CFGV</span><span class="plain-syntax"> == </span><span class="constant-syntax">1</span><span class="plain-syntax">) </span><span class="reserved-syntax">rtrue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">rfalse</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></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>
|
|
|
|
<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="commentary">We keep track of (c) by watching for calls to <span class="extract"><span class="extract-syntax">SignalMapChange()</span></span> 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 <span class="extract"><span class="extract-syntax">room_index</span></span> and by the flags in the
|
|
<span class="extract"><span class="extract-syntax">DoorRoutingViable</span></span> array respectively.
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">NUM_DOORS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ICOUNT_DOOR</span><span class="plain-syntax">;</span>
|
|
<span class="reserved-syntax">Constant</span><span class="plain-syntax"> </span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ICOUNT_ROOM</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="reserved-syntax">Array</span><span class="plain-syntax"> </span><span class="identifier-syntax">DoorRoutingViable</span><span class="plain-syntax"> -> </span><span class="identifier-syntax">NUM_DOORS</span><span class="plain-syntax">+1;</span>
|
|
|
|
<span class="identifier-syntax">Global</span><span class="plain-syntax"> </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="identifier-syntax">Global</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_filter</span><span class="plain-syntax">; </span><span class="identifier-syntax">Global</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_use_doors</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">SignalMapChange</span><span class="plain-syntax">; </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">; ];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">MapRouteTo</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">count</span><span class="plain-syntax"> </span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="identifier-syntax">oyi</span><span class="plain-syntax"> </span><span class="identifier-syntax">ds</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="reserved-syntax">to</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">to</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="reserved-syntax">to</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">last_filter</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">filter</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">last_use_doors</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">)) </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">oyi</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="identifier-syntax">oy</span><span class="plain-syntax">))) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> == -1) </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> = </span><span class="identifier-syntax">oyi</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> = -1;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">oyi</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">K4_door</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">ds</span><span class="plain-syntax"> = </span><span class="reserved-syntax">false</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> & </span><span class="constant-syntax">2</span><span class="plain-syntax">) ||</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">open</span><span class="plain-syntax">) || ((</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">openable</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">hasnt</span><span class="plain-syntax"> </span><span class="identifier-syntax">locked</span><span class="plain-syntax">))) </span><span class="identifier-syntax">ds</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">DoorRoutingViable</span><span class="plain-syntax">-></span><span class="identifier-syntax">oyi</span><span class="plain-syntax"> ~= </span><span class="identifier-syntax">ds</span><span class="plain-syntax">) </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">DoorRoutingViable</span><span class="plain-syntax">-></span><span class="identifier-syntax">oyi</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ds</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">oyi</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">UseFastRouteFinding</span><span class="plain-syntax">()) </span><span class="identifier-syntax">ComputeFWMatrix</span><span class="plain-syntax">(</span><span class="identifier-syntax">filter</span><span class="plain-syntax">, </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">map_has_changed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">false</span><span class="plain-syntax">; </span><span class="identifier-syntax">last_filter</span><span class="plain-syntax"> = </span><span class="identifier-syntax">filter</span><span class="plain-syntax">; </span><span class="identifier-syntax">last_use_doors</span><span class="plain-syntax"> = </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">UseFastRouteFinding</span><span class="plain-syntax">()) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">count</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FastCountRouteTo</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">filter</span><span class="plain-syntax">, </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FastRouteTo</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">filter</span><span class="plain-syntax">, </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">count</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">SlowCountRouteTo</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">filter</span><span class="plain-syntax">, </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">SlowRouteTo</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">filter</span><span class="plain-syntax">, </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>§3. </b>When this code became part of <span class="extract"><span class="extract-syntax">WorldModelKit</span></span>, and thus needed to be linked
|
|
at the Inter level rather than mixed in as raw I6 code as in the pre-2020 days,
|
|
the mechanism for selecting the route-finding algorithm needed to change.
|
|
Previously, if the constant <span class="extract"><span class="extract-syntax">FAST_ROUTE_FINDING</span></span> was defined, the matrix
|
|
<span class="extract"><span class="extract-syntax">FW_Matrix</span></span> and its functions would be compiled, and otherwise the functions
|
|
with names beginning <span class="extract"><span class="extract-syntax">Slow...</span></span> would be compiled.
|
|
</p>
|
|
|
|
<p class="commentary">To avoid having to make two different linkable binaries of <span class="extract"><span class="extract-syntax">WorldModelKit</span></span>,
|
|
one in which fast route finding is used and one in which it isn't, we now
|
|
instead compile the functions either way (they are not large) and the Inform
|
|
compiler defines the constant <span class="extract"><span class="extract-syntax">FWMATRIX_SIZE</span></span> to be 2 for slow route-finding
|
|
(wasting only a negligible number of words for an unused array) and \(R^2\),
|
|
where \(R\) is the number of rooms, for fast route-finding.
|
|
</p>
|
|
|
|
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>§4. 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="commentary">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="commentary">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="commentary">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="commentary">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="displayed-code all-displayed-code code-font">
|
|
<span class="reserved-syntax">Array</span><span class="plain-syntax"> </span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax"> --> </span><span class="identifier-syntax">FWMATRIX_SIZE</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">FastRouteTo</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">diri</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> </span><span class="identifier-syntax">dir</span><span class="plain-syntax"> </span><span class="identifier-syntax">oy</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">to</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="reserved-syntax">to</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))/</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">diri</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="reserved-syntax">to</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))%</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">dir</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">K3_direction</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">i</span><span class="plain-syntax"> == </span><span class="identifier-syntax">diri</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">dir</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">++;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">FastCountRouteTo</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">to</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="reserved-syntax">to</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))/</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">k</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">k</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">ComputeFWMatrix</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="identifier-syntax">oj</span><span class="plain-syntax"> </span><span class="identifier-syntax">axy</span><span class="plain-syntax"> </span><span class="identifier-syntax">ayj</span><span class="plain-syntax"> </span><span class="identifier-syntax">axj</span><span class="plain-syntax"> </span><span class="identifier-syntax">dir</span><span class="plain-syntax"> </span><span class="identifier-syntax">diri</span><span class="plain-syntax"> </span><span class="identifier-syntax">nd</span><span class="plain-syntax"> </span><span class="identifier-syntax">row</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">) = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">row</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">IK1_Count</span><span class="plain-syntax">)*</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">diri</span><span class="plain-syntax">=0: </span><span class="identifier-syntax">diri</span><span class="plain-syntax"><</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">: </span><span class="identifier-syntax">diri</span><span class="plain-syntax">++) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">ox</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Map_Storage</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">row</span><span class="plain-syntax">+</span><span class="identifier-syntax">diri</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">ox</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">) = </span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax"> + </span><span class="identifier-syntax">diri</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> && (</span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">K4_door</span><span class="plain-syntax">) &&</span>
|
|
<span class="plain-syntax"> ((</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> & </span><span class="constant-syntax">2</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">DoorRoutingViable</span><span class="plain-syntax">->(</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">IK4_Count</span><span class="plain-syntax">)))) {</span>
|
|
<span class="plain-syntax"> @</span><span class="identifier-syntax">push</span><span class="plain-syntax"> </span><span class="identifier-syntax">location</span><span class="plain-syntax">; </span><span class="identifier-syntax">location</span><span class="plain-syntax"> = </span><span class="identifier-syntax">oy</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">ox</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">door_to</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> @</span><span class="identifier-syntax">pull</span><span class="plain-syntax"> </span><span class="identifier-syntax">location</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">ox</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">) = </span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax"> + </span><span class="identifier-syntax">diri</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ox</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">axy</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))/</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">axy</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oj</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">oj</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax"> >= </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">ayj</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">oj</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))/</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ayj</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "Is it faster to go from ", (name) ox, " to ",</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax"> (name) oj, " via ", (name) oy, "?^";</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">axj</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">oj</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))/</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">axj</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">axy</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ayj</span><span class="plain-syntax"> < </span><span class="identifier-syntax">axj</span><span class="plain-syntax">)) {</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "Yes^";</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">oj</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">) =</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">axy</span><span class="plain-syntax"> + </span><span class="identifier-syntax">ayj</span><span class="plain-syntax">)*</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax"> +</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">FWMatrix</span><span class="plain-syntax">-->(</span><span class="identifier-syntax">ox</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">*</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax"> + </span><span class="identifier-syntax">oy</span><span class="plain-syntax">.</span><span class="identifier-syntax">room_index</span><span class="plain-syntax">))%</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>§5. 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="commentary">For each room \(R_z\), the property <span class="extract"><span class="extract-syntax">vector</span></span> 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 <span class="extract"><span class="extract-syntax">vector</span></span> direction
|
|
from where we currently stand until we reach \(R_y\). Since every room needs
|
|
a <span class="extract"><span class="extract-syntax">vector</span></span> value, this requires \(n\) words of storage. (The <span class="extract"><span class="extract-syntax">vector</span></span> 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="commentary">The method can be summed up thus:
|
|
</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="commentary">To prove the correctness of this, we show inductively that after round \(n\)
|
|
we have set the <span class="extract"><span class="extract-syntax">vector</span></span> for every room having a shortest path to \(R_y\) of
|
|
length \(n\), and that every <span class="extract"><span class="extract-syntax">vector</span></span> points to a room having a <span class="extract"><span class="extract-syntax">vector</span></span> in
|
|
the direction of the shortest path from there to \(R_y\).
|
|
</p>
|
|
|
|
<pre class="displayed-code all-displayed-code code-font">
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">SlowRouteTo</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">obj</span><span class="plain-syntax"> </span><span class="identifier-syntax">dir</span><span class="plain-syntax"> </span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="identifier-syntax">progressed</span><span class="plain-syntax"> </span><span class="identifier-syntax">sl</span><span class="plain-syntax"> </span><span class="identifier-syntax">through_door</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="reserved-syntax">to</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">to</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">obj</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "Routing from ", (the) from, " to ", (the) to, "^";</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="reserved-syntax">true</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">progressed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">false</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "Pass begins^";</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">obj</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="identifier-syntax">obj</span><span class="plain-syntax">)))</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">dir</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">K3_direction</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Map_Storage</span><span class="plain-syntax">-->((</span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">IK1_Count</span><span class="plain-syntax">)*</span><span class="identifier-syntax">No_Directions</span><span class="plain-syntax"> + </span><span class="identifier-syntax">dir</span><span class="plain-syntax">.</span><span class="identifier-syntax">IK3_Count</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint (the) obj, " > ", (the) dir, " > ", (the) in_direction, "^";</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax">)))) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> = </span><span class="identifier-syntax">dir</span><span class="plain-syntax"> | </span><span class="identifier-syntax">WORD_HIGHBIT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "* ", (the) obj, " vector is ", (the) dir, "^";</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">progressed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> && (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="reserved-syntax">ofclass</span><span class="plain-syntax"> </span><span class="identifier-syntax">K4_door</span><span class="plain-syntax">) &&</span>
|
|
<span class="plain-syntax"> ((</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> & </span><span class="constant-syntax">2</span><span class="plain-syntax">) ||</span>
|
|
<span class="plain-syntax"> (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">open</span><span class="plain-syntax">) ||</span>
|
|
<span class="plain-syntax"> ((</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">openable</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">in_direction</span><span class="plain-syntax"> </span><span class="reserved-syntax">hasnt</span><span class="plain-syntax"> </span><span class="identifier-syntax">locked</span><span class="plain-syntax">)))) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">sl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">location</span><span class="plain-syntax">; </span><span class="identifier-syntax">location</span><span class="plain-syntax"> = </span><span class="identifier-syntax">obj</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">through_door</span><span class="plain-syntax"> = </span><span class="identifier-syntax">in_direction</span><span class="plain-syntax">.</span><span class="identifier-syntax">door_to</span><span class="plain-syntax">();</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">location</span><span class="plain-syntax"> = </span><span class="identifier-syntax">sl</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "Through door is ", (the) through_door, "^";</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">through_door</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && (</span><span class="identifier-syntax">through_door</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && (</span><span class="identifier-syntax">through_door</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> > </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
|
|
<span class="plain-syntax"> && ((</span><span class="identifier-syntax">filter</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">filter</span><span class="plain-syntax">(</span><span class="identifier-syntax">through_door</span><span class="plain-syntax">)))) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> = </span><span class="identifier-syntax">dir</span><span class="plain-syntax"> | </span><span class="identifier-syntax">WORD_HIGHBIT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="comment-syntax">rint "* ", (the) obj, " vector is ", (the) dir, "^";</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">progressed</span><span class="plain-syntax"> = </span><span class="reserved-syntax">true</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">continue</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">objectloop</span><span class="plain-syntax"> (</span><span class="identifier-syntax">obj</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) </span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> = </span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax"> &~ </span><span class="identifier-syntax">WORD_HIGHBIT</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">progressed</span><span class="plain-syntax"> == </span><span class="reserved-syntax">false</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax">];</span>
|
|
|
|
<span class="plain-syntax">[ </span><span class="identifier-syntax">SlowCountRouteTo</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="identifier-syntax">filter</span><span class="plain-syntax"> </span><span class="identifier-syntax">use_doors</span><span class="plain-syntax"> </span><span class="identifier-syntax">obj</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="reserved-syntax">to</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="reserved-syntax">to</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax"> && </span><span class="reserved-syntax">to</span><span class="plain-syntax"> </span><span class="reserved-syntax">has</span><span class="plain-syntax"> </span><span class="identifier-syntax">mark_as_room</span><span class="plain-syntax">) {</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">obj</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MapRouteTo</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">,</span><span class="reserved-syntax">to</span><span class="plain-syntax">,</span><span class="identifier-syntax">filter</span><span class="plain-syntax">,</span><span class="identifier-syntax">use_doors</span><span class="plain-syntax">);</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">obj</span><span class="plain-syntax"> == </span><span class="reserved-syntax">nothing</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">obj</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">obj</span><span class="plain-syntax"> ~= </span><span class="reserved-syntax">to</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">i</span><span class="plain-syntax"><</span><span class="identifier-syntax">NUM_ROOMS</span><span class="plain-syntax">)) { </span><span class="identifier-syntax">i</span><span class="plain-syntax">++; </span><span class="identifier-syntax">obj</span><span class="plain-syntax"> = </span><span class="identifier-syntax">MapConnection</span><span class="plain-syntax">(</span><span class="identifier-syntax">obj</span><span class="plain-syntax">,</span><span class="identifier-syntax">obj</span><span class="plain-syntax">.</span><span class="identifier-syntax">vector</span><span class="plain-syntax">); }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
|
|
<span class="plain-syntax"> }</span>
|
|
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> -1;</span>
|
|
<span class="plain-syntax">];</span>
|
|
</pre>
|
|
<nav role="progress"><div class="progresscontainer">
|
|
<ul class="progressbar"><li class="progressprev"><a href="S-wrl.html">❮</a></li><li class="progresssection"><a href="S-msc.html">msc</a></li><li class="progresssection"><a href="S-gll.html">gll</a></li><li class="progresssection"><a href="S-zmc.html">zmc</a></li><li class="progresssection"><a href="S-lgh.html">lgh</a></li><li class="progresssection"><a href="S-lst.html">lst</a></li><li class="progresssection"><a href="S-ord.html">ord</a></li><li class="progresssection"><a href="S-act.html">act</a></li><li class="progresssection"><a href="S-act2.html">act2</a></li><li class="progresssection"><a href="S-fgr.html">fgr</a></li><li class="progresssection"><a href="S-otf.html">otf</a></li><li class="progresssection"><a href="S-prn.html">prn</a></li><li class="progresssection"><a href="S-wrl.html">wrl</a></li><li class="progresscurrent">mpr</li><li class="progresssection"><a href="S-rtp.html">rtp</a></li><li class="progresssection"><a href="S-tm.html">tm</a></li><li class="progresssection"><a href="S-tst.html">tst</a></li><li class="progresssection"><a href="S-chr.html">chr</a></li><li class="progresssection"><a href="S-str.html">str</a></li><li class="progressnext"><a href="S-rtp.html">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|