mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 08:34:22 +03:00
4130 lines
524 KiB
HTML
4130 lines
524 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>3/sg</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="../webs.html">Sources</a></h1>
|
|
<ul>
|
|
<li><a href="../compiler.html"><b>compiler</b></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>Compiler Webs</h2>
|
|
<ul>
|
|
<li><a href="../inbuild/index.html">inbuild</a></li>
|
|
<li><a href="../inform7/index.html">inform7</a></li>
|
|
<li><a href="../inter/index.html">inter</a></li>
|
|
</ul>
|
|
<h2>Inbuild Modules</h2>
|
|
<ul>
|
|
<li><a href="../inbuild-module/index.html">inbuild</a></li>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../words-module/index.html">words</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
</ul>
|
|
<h2>Inform7 Modules</h2>
|
|
<ul>
|
|
<li><a href="../core-module/index.html">core</a></li>
|
|
<li><a href="../problems-module/index.html">problems</a></li>
|
|
<li><a href="../inflections-module/index.html">inflections</a></li>
|
|
<li><a href="../linguistics-module/index.html">linguistics</a></li>
|
|
<li><a href="../kinds-module/index.html">kinds</a></li>
|
|
<li><a href="../if-module/index.html">if</a></li>
|
|
<li><a href="../multimedia-module/index.html">multimedia</a></li>
|
|
<li><a href="../index-module/index.html">index</a></li>
|
|
</ul>
|
|
<h2>Inter Modules</h2>
|
|
<ul>
|
|
<li><a href="../inter-module/index.html">inter</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul>
|
|
<h2>Foundation</h2>
|
|
<ul>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
</ul>
|
|
|
|
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of '3/sm2' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">if</a></li><li><a href="index.html#3">Chapter 3: Space and Time</a></li><li><b>Spatial Map</b></li></ul><p class="purpose">To fit the map of the rooms in the game into a cubical grid, preserving distances and angles where possible, and so to give each room approximate coordinate locations.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP8">§8. Grand strategy</a></li><li><a href="#SP8_1">§8.1. Mapping data attached to each room</a></li><li><a href="#SP8_4">§8.4. Page directions</a></li><li><a href="#SP8_15">§8.15. Benchmark room</a></li><li><a href="#SP8_16">§8.16. Map reading</a></li><li><a href="#SP12">§12. Submap construction</a></li><li><a href="#SP8_24">§8.24. Partitioning to component submaps</a></li><li><a href="#SP8_26">§8.26. Movements of single rooms</a></li><li><a href="#SP8_27">§8.27. Synchronising movements of locked rooms</a></li><li><a href="#SP8_29">§8.29. Positioning within components</a></li><li><a href="#SP18">§18. Heat</a></li><li><a href="#SP23">§23. Subdividing our submap</a></li><li><a href="#SP24">§24. Finding how to divide</a></li><li><a href="#SP26">§26. Zones 1 and 2 for a single cut</a></li><li><a href="#SP28">§28. Zones 1 and 2 for a double cut</a></li><li><a href="#SP30">§30. Tactics</a></li><li><a href="#SP31">§31. The cooling tactic</a></li><li><a href="#SP34">§34. The quenching tactic</a></li><li><a href="#SP35">§35. The diffusion tactic</a></li><li><a href="#SP37">§37. The radiation tactic</a></li><li><a href="#SP8_31">§8.31. The explosion tactic</a></li><li><a href="#SP8_32">§8.32. Stage 3, positioning the components</a></li><li><a href="#SP8_34">§8.34. Stage 5, bounding the universe</a></li><li><a href="#SP8_35">§8.35. Stage 6, removing blank planes</a></li><li><a href="#SP43">§43. Precis</a></li><li><a href="#SP46">§46. Unit testing</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>We assign (x, y, z) coordinates to each room, aiming to make the
|
|
descriptive map connections ("The Ballroom is east of the Old Kitchens")
|
|
as plausible as possible in coordinate terms. This is potentially a
|
|
research-level problem in graph theory or aesthetics. A problem like it was
|
|
recently set in a world programming competition: to turn spatial
|
|
coordinates into a simplified subway map. This is almost the reverse, but
|
|
has a certain amount in common with it.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We will partition the set of rooms into "components", which are disjoint
|
|
nonempty collections of rooms joined together by proximity. This has two
|
|
forms:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(i) Map connections in directions along lattice lines (EAST, UP, and so on
|
|
but not INSIDE or OUTSIDE);
|
|
</li><li>(ii) Locks placed between rooms by sentences intended to give this algorithm
|
|
hints about layout.
|
|
</li></ul>
|
|
<p class="inwebparagraph">As we will see, we will map rooms using a symmetric form of relationships:
|
|
if X relates to Y then Y relates to X. This will take some fixing, because
|
|
map connections in Inform needn't be symmetrical.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We must then solve two different problems. The first is to place rooms at
|
|
grid positions within each individual component. We assign each possible
|
|
arrangement a numerical measure of its geometric distortion, and then try
|
|
to minimise this, but of course any exhaustive search would be
|
|
prohibitively slow. This problem is quite likely NP-complete, and it looks
|
|
likely that we can embed notorious problems in complexity theory within it
|
|
(say, the bandwidth minimization problem). We do have the advantage of
|
|
experience about what IF maps look like, and of not having to deal well
|
|
with bizarre maps, but still, we shouldn't expect to achieve a perfect
|
|
choice. We must be very careful about running time; it's unacceptable for
|
|
the Inform indexer to take longer to run than Inform itself. The code below
|
|
is roughly quadratic in the number of rooms, which is a reasonable
|
|
compromise given how few works of IF have really enormous room counts.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The second problem is to place the components onto a global grid so that
|
|
they make sensible use of space on the index page, but don't get in each
|
|
other's way.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>A "connected submap" is a map formed from some subset of the rooms
|
|
in the model world, together with any spatial relationships between them,
|
|
such that it's possible to go from any X to any Y in the submap using only
|
|
some sequence of these relationships.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Connected submaps will arise initially because we'll take every component
|
|
of the map and make it into a connected submap; but then more will exist
|
|
temporarily as we cut these up. Each room will, at any given time, belong
|
|
to exactly one submap.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">At any given point in our calculations each room has a grid location which
|
|
is a triple of integers (x, y, z). The position of the origin is
|
|
undefined, and not relevant, since only the location of one room relative
|
|
to another is important. We will cache the values of the corner points of
|
|
the smallest cuboid (x_0, y_0, z_0) to (x_1, y_1, z_1) which contains
|
|
all of the rooms in our submap. Similarly, we cache the penalty score for
|
|
the current arrangement of rooms relative to each other within the submap
|
|
as the "heat", a term to be explained later.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">connected_submap</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">first_room_in_submap</span><span class="plain">; </span> <span class="comment">double-headed linked list of rooms</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">last_room_in_submap</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">bounds</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain">; </span> <span class="comment">current penalty score for bad placement of rooms</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">positioned</span><span class="plain">; </span> <span class="comment">already placed within the global map grid?</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">incidence_cache</span><span class="plain">; </span> <span class="comment">how many of our rooms occupy each grid position?</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">incidence_cache_size</span><span class="plain">; </span> <span class="comment">how large that cache is</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">incidence_cache_bounds</span><span class="plain">; </span> <span class="comment">bounds of the incidence cache array</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">superpositions</span><span class="plain">; </span> <span class="comment">number of pairs of rooms which share the same grid location</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">connected_submap</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure connected_submap is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>Just as each submap has a bounding cuboid, so does the whole assemblage:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">Universe</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>One special room is the "benchmark", from which the map is arranged.
|
|
This is usually the room in which the player begins.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">benchmark_room</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>We are going to be iterating through the set of rooms often. Looping over
|
|
all rooms can afford to be fairly slow, but it's essential in order to keep
|
|
the running time down that we loop through submaps with overhead no worse
|
|
than the number of rooms in the submap; this is why we keep the linked list.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_OBJECT_INSTANCES</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Spatial::object_is_a_room</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">))</span>
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain">; </span><span class="identifier">R</span><span class="plain">; </span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>next_room_in_submap</span><span class="plain">)</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>These algorithms are trying to do something computationally expensive, so
|
|
it's useful to keep track of how much time they cost. The unit of currency
|
|
here is the "drogna"; 1 drogna is equivalent to a single map or lock lookup,
|
|
or a single exit heat calculation.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">drognas_spent</span><span class="plain"> = 0; </span> <span class="comment">in order to measure roughly how much work we're doing</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cutpoint_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">division_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">slide_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cooling_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">quenching_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">diffusion_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">radiation_spending</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">explosion_spending</span><span class="plain"> = 0;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. Grand strategy. </b>Here is the six-stage strategy. I estimate that the running time is as
|
|
follows, where R is the number of rooms:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(1) Linear time, O(R), so essentially instant.
|
|
</li><li>(2) Linear time, O(R), so essentially instant.
|
|
</li><li>(3) About O(R^2log R), at worst, but generally better in practical cases.
|
|
</li><li>(4) This could be as bad as O(R^2), but only in bizarre circumstances.
|
|
</li><li>(5) Linear time, O(R), so essentially instant.
|
|
</li><li>(6) In theory about O(R^{4/3}), but in practice O(R).
|
|
</li></ul>
|
|
<p class="inwebparagraph">We allow this routine to be called more than once only for the convenience of
|
|
the unit test below, which makes spatial positioning happen early in order
|
|
to get the results in time to write them in the story file.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">spatial_coordinates_established</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">partitioned_into_components</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::establish_spatial_coordinates</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spatial_coordinates_established</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Log::aspect_switched_on</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_DA</span><span class="plain">)) </span><span class="functiontext">PL::SpatialMap::log_precis_of_map</span><span class="plain">();</span>
|
|
<span class="identifier">Universe</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<<span class="cwebmacro">(1) Create the spatial relationship arrays</span> <span class="cwebmacronumber">8.17</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">(2) Partition the set of rooms into component submaps</span> <span class="cwebmacronumber">8.24</span>><span class="plain">;</span>
|
|
<span class="identifier">partitioned_into_components</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">(3) Position the rooms within each component</span> <span class="cwebmacronumber">8.29</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">(4) Position the components in space</span> <span class="cwebmacronumber">8.32</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">(5) Find the universal bounding cuboid</span> <span class="cwebmacronumber">8.34</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">(6) Remove any blank lateral planes</span> <span class="cwebmacronumber">8.35</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">(5) Find the universal bounding cuboid</span> <span class="cwebmacronumber">8.34</span>><span class="plain">;</span>
|
|
<span class="identifier">spatial_coordinates_established</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::establish_spatial_coordinates is used in <a href="#SP46">§46</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_1"></a><b>§8.1. Mapping data attached to each room. </b>The (x, y, z) position, and the submap, are straightforward enough;
|
|
during our calculations (x, y, z) are relative coordinates to other rooms
|
|
in the same submap, but they are ultimately replaced with absolute
|
|
coordinates, once the submaps have themselves been placed in space.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The colour and mapping parameters are used for plotting purposes, so we
|
|
won't need them in this section.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::initialise_mapping_data</span><span class="plain">(</span><span class="reserved">map_data</span><span class="plain"> *</span><span class="identifier">md</span><span class="plain">) {</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>world_index_colour</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>world_index_text_colour</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>position</span><span class="plain"> = </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>saved_gridpos</span><span class="plain"> = </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">md</span><span class="plain">-</span><span class="element">>next_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">md</span><span class="plain">-</span><span class="element">>lock_exits</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::EPSMap::prepare_map_parameter_scope</span><span class="plain">(&(</span><span class="identifier">md</span><span class="plain">-</span><span class="element">>local_map_parameters</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::initialise_mapping_data is used in 3/tm (<a href="3-tm.html#SP9">§9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_2"></a><b>§8.2. </b>To make the code less cumbersome to read, all access to the position
|
|
will be using the following:
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>position</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">O</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>position</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">) </span><span class="functiontext">PL::SpatialMap::move_room_within_submap</span><span class="plain">(</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::set_room_position_breaking_cache</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>position</span><span class="plain"> = </span><span class="identifier">P</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::set_room_position is used in <a href="#SP8_26">§8.26</a>, <a href="#SP8_27">§8.27</a>, <a href="#SP30">§30</a>, <a href="#SP37_1">§37.1</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::set_room_position_breaking_cache is used in <a href="#SP8_21">§8.21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_3"></a><b>§8.3. </b>Locking is a way to influence the algorithm in this section by forcing a
|
|
given exit to be locked in place, forbidding it to be distorted.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::lock_exit_in_place</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I2</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::lock_one_exit</span><span class="plain">(</span><span class="identifier">I2</span><span class="plain">, </span><span class="identifier">exit</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::lock_one_exit</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">), </span><span class="identifier">I2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::lock_one_exit</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Mapping clue: put $O to the %s of $O\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">T</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">), </span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">)-</span><span class="element">>lock_exits</span><span class="plain">[</span><span class="identifier">exit</span><span class="plain">] = </span><span class="identifier">T</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::lock_exit_in_place is used in 3/em (<a href="3-em.html#SP22_2">§22.2</a>).</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::lock_one_exit appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_4"></a><b>§8.4. Page directions. </b>These are any of the 12 standard IF directions (N, NE, NW, S, SE, SW, E, W,
|
|
U, D, IN, OUT), and are indexed with an number between 0 and 11 inclusive.
|
|
These are so called because they refer to directions on the page on which
|
|
the map will be plotted — the page direction 6 really means rightwards, not
|
|
east, but it's still convenient to think of them that way.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For most Inform projects, page directions correspond to directions in the
|
|
story file. But that needn't be true; some story files create exotic directions
|
|
like "port" and "starboard". So the following array gives the correspondence
|
|
of story directions to page directions; if the value is 12 or more, the direction
|
|
won't be shown on the index at all. The initial setup is for the 12 standard
|
|
story directions to correspond exactly to the 12 page directions, then, and
|
|
for any subsequent story directions to be unshown:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">];</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::initialise_page_directions</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">registered_directions</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::initialise_page_directions is used in 3/em (<a href="3-em.html#SP14">§14</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_5"></a><b>§8.5. </b>If we want to show one of the exotic directions, we can use a sentence like:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Index map with starboard mapped as east.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">When we read this, we associate direction object 13, say (the starboard
|
|
direction) with page direction 6:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::map_direction_as_if</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I2</span><span class="plain">) {</span>
|
|
<span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">] = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">I2</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::mapped_as_if</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="identifier">i</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">D</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">, </span><span class="identifier">K_direction</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain"> == </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">D</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::map_direction_as_if is used in 3/em (<a href="3-em.html#SP22_1">§22.1</a>).</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::mapped_as_if is used in 3/hm (<a href="3-hm.html#SP6_3_4">§6.3.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_6"></a><b>§8.6. </b>This is therefore how we know whether a given story direction will actually
|
|
be visible on the map we draw:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::direction_is_mappable</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">page_direction</span><span class="plain"> >= 12) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::direction_is_mappable is used in 3/hm (<a href="3-hm.html#SP1_3">§1.3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_7"></a><b>§8.7. </b>Each page direction involves a given offset in lattice coordinates: for
|
|
example, direction 6 (E) involves an offset of (1, 0, 0), because a move
|
|
in this map direction increases the x-coordinate by 1 and leaves y and z
|
|
unchanged.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">N_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NE_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NW_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">S_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SE_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">SW_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">E_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">W_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 8: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">U_vector</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 9: </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">D_vector</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::direction_as_vector is used in <a href="#SP8_10">§8.10</a>, <a href="#SP8_11">§8.11</a>, <a href="#SP8_27">§8.27</a>, <a href="#SP21">§21</a>, <a href="#SP22">§22</a>, <a href="#SP23_1_4">§23.1.4</a>, <a href="#SP33">§33</a>, <a href="#SP37_1">§37.1</a>, 3/hm (<a href="3-hm.html#SP1_3_4">§1.3.4</a>), 3/em (<a href="3-em.html#SP25_6_1_2">§25.6.1.2</a>, <a href="3-em.html#SP33">§33</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_8"></a><b>§8.8. </b>Page directions all have opposites:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span><span class="reserved">return</span><span class="plain"> 3; </span> <span class="comment">N — S</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="reserved">return</span><span class="plain"> 5; </span> <span class="comment">NE — SW</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="reserved">return</span><span class="plain"> 4; </span> <span class="comment">NW — SE</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">S — N</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="reserved">return</span><span class="plain"> 2; </span> <span class="comment">SE — NW</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><span class="reserved">return</span><span class="plain"> 1; </span> <span class="comment">SW — NE</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><span class="reserved">return</span><span class="plain"> 7; </span> <span class="comment">E — W</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: </span><span class="reserved">return</span><span class="plain"> 6; </span> <span class="comment">W — E</span>
|
|
<span class="reserved">case</span><span class="plain"> 8: </span><span class="reserved">return</span><span class="plain"> 9; </span> <span class="comment">UP — DOWN</span>
|
|
<span class="reserved">case</span><span class="plain"> 9: </span><span class="reserved">return</span><span class="plain"> 8; </span> <span class="comment">DOWN — UP</span>
|
|
<span class="reserved">case</span><span class="plain"> 10: </span><span class="reserved">return</span><span class="plain"> 11; </span> <span class="comment">IN — OUT</span>
|
|
<span class="reserved">case</span><span class="plain"> 11: </span><span class="reserved">return</span><span class="plain"> 10; </span> <span class="comment">OUT — IN</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::opposite is used in <a href="#SP8_3">§8.3</a>, <a href="#SP8_17_1">§8.17.1</a>, <a href="#SP8_17_1_1">§8.17.1.1</a>, <a href="#SP8_17_1_3">§8.17.1.3</a>, <a href="#SP8_17_1_4">§8.17.1.4</a>, <a href="#SP9">§9</a>, <a href="#SP25_2_3_2">§25.2.3.2</a>, <a href="#SP8_30">§8.30</a>, <a href="#SP43_3">§43.3</a>, 3/em (<a href="3-em.html#SP25_6_1">§25.6.1</a>, <a href="3-em.html#SP25_6_1_1">§25.6.1.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_9"></a><b>§8.9. </b>Lateral directions can be rotated clockwise (seen from above), if <code class="display"><span class="extract">way</span></code>
|
|
is positive; or anticlockwise if it's negative.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::rotate_direction</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">way</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">N</span><span class="plain"> = 1; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">way</span><span class="plain"> < 0) </span><span class="identifier">N</span><span class="plain"> = 7;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><=</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span><span class="identifier">page_direction</span><span class="plain"> = 1; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">N — NE</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="identifier">page_direction</span><span class="plain"> = 6; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">NE — E</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="identifier">page_direction</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">NW — N</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="identifier">page_direction</span><span class="plain"> = 5; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">S — SW</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="identifier">page_direction</span><span class="plain"> = 3; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">SE — S</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><span class="identifier">page_direction</span><span class="plain"> = 7; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">SW — W</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><span class="identifier">page_direction</span><span class="plain"> = 4; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">E — SE</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: </span><span class="identifier">page_direction</span><span class="plain"> = 2; </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">W — NW</span>
|
|
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">page_direction</span><span class="plain"> = -1; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::rotate_direction is used in <a href="#SP8_17_1">§8.17.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_10"></a><b>§8.10. </b>Lateral directions are the ones which (a) are mappable, and (b) involve
|
|
movement along the x-y grid lines.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::direction_is_lateral</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Geometry::vec_lateral</span><span class="plain">(</span>
|
|
<span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">story_direction</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::direction_is_lateral is used in 3/hm (<a href="3-hm.html#SP1_3_4">§1.3.4</a>), 3/em (<a href="3-em.html#SP22_2">§22.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_11"></a><b>§8.11. </b>Along-lattice directions are those which (a) are mappable, and (b) involve
|
|
movement along grid lines. Clearly lateral directions are along-lattice, but
|
|
not necessarily vice versa.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::direction_is_along_lattice</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">story_direction</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">, </span><span class="identifier">Zero_vector</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::direction_is_along_lattice is used in <a href="#SP21">§21</a>, <a href="#SP22">§22</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_12"></a><b>§8.12. </b>For speed, we don't call these functions when looping through directions;
|
|
we use these hard-wired macros instead.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><12; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_STORY_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">registered_directions</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><10; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NONLATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=10; </span><span class="identifier">i</span><span class="plain"><12; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP8_13"></a><b>§8.13. </b>Strictly speaking the following is more to do with rendering than
|
|
calculating, but it seems to belong here. In the HTML map, rooms have a
|
|
five-by-five cell grid, and exits are plotted at positions on the
|
|
boundary of that grid; for example, a line running in page direction 6
|
|
will be plotted with an icon at cell (4, 2).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cell_position_for_direction</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">mx</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">my</span><span class="plain">) {</span>
|
|
<span class="plain">*</span><span class="identifier">mx</span><span class="plain"> = 0; *</span><span class="identifier">my</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: *</span><span class="identifier">mx</span><span class="plain"> = 2; *</span><span class="identifier">my</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: *</span><span class="identifier">mx</span><span class="plain"> = 4; *</span><span class="identifier">my</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: *</span><span class="identifier">mx</span><span class="plain"> = 0; *</span><span class="identifier">my</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: *</span><span class="identifier">mx</span><span class="plain"> = 2; *</span><span class="identifier">my</span><span class="plain"> = 4; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: *</span><span class="identifier">mx</span><span class="plain"> = 4; *</span><span class="identifier">my</span><span class="plain"> = 4; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: *</span><span class="identifier">mx</span><span class="plain"> = 0; *</span><span class="identifier">my</span><span class="plain"> = 4; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: *</span><span class="identifier">mx</span><span class="plain"> = 4; *</span><span class="identifier">my</span><span class="plain"> = 2; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: *</span><span class="identifier">mx</span><span class="plain"> = 0; *</span><span class="identifier">my</span><span class="plain"> = 2; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 8: *</span><span class="identifier">mx</span><span class="plain"> = 1; *</span><span class="identifier">my</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 9: *</span><span class="identifier">mx</span><span class="plain"> = 3; *</span><span class="identifier">my</span><span class="plain"> = 4; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 10: *</span><span class="identifier">mx</span><span class="plain"> = 4; *</span><span class="identifier">my</span><span class="plain"> = 3; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 11: *</span><span class="identifier">mx</span><span class="plain"> = 0; *</span><span class="identifier">my</span><span class="plain"> = 1; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::cell_position_for_direction is used in 3/hm (<a href="3-hm.html#SP1_3_4">§1.3.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_14"></a><b>§8.14. </b>And similarly:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::find_icon_label</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"n"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"ne"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"nw"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"s"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"se"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"sw"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"e"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"w"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 8: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"u"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 9: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"d"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 10: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"in"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 11: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"out"</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">story_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">story_direction</span><span class="plain"> < 0) || (</span><span class="identifier">story_direction</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"<none>"</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">page_direction</span><span class="plain"> = </span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">story_direction</span><span class="plain">];</span>
|
|
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">page_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 0: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"north"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"northeast"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"northwest"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"south"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 4: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"southeast"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 5: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"southwest"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 6: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"east"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 7: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"west"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 8: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"up"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 9: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"down"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 10: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"inside"</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 11: </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"outside"</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="string">"<none>"</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_icon_label is used in <a href="#SP33">§33</a>, <a href="#SP34_1">§34.1</a>, <a href="#SP35_1">§35.1</a>, <a href="#SP37_1">§37.1</a>, 3/hm (<a href="3-hm.html#SP10_2_1">§10.2.1</a>).</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::usual_Inform_direction_name is used in <a href="#SP8_3">§8.3</a>, <a href="#SP23_1_2">§23.1.2</a>, <a href="#SP43_3">§43.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_15"></a><b>§8.15. Benchmark room. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::establish_benchmark_room</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">benchmark_room</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">benchmark_room</span><span class="plain"> = </span><span class="functiontext">PL::Player::get_start_room</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">benchmark_room</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) { </span><span class="identifier">benchmark_room</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">; </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no room exists in mapping"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::establish_benchmark_room is used in <a href="#SP46">§46</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_16"></a><b>§8.16. Map reading. </b>The map is read in the first instance by the <code class="display"><span class="extract">PL::SpatialMap::room_exit</span></code>
|
|
routine below, which works out what room the exit leads to, perhaps via a
|
|
door, which we take a note of if asked to do so.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">origin</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir_num</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">via</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">via</span><span class="plain">) *</span><span class="identifier">via</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">origin</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="functiontext">PL::Spatial::object_is_a_room</span><span class="plain">(</span><span class="identifier">origin</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">dir_num</span><span class="plain"> < 0) || (</span><span class="identifier">dir_num</span><span class="plain"> >= </span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">ultimate_destination</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">immediate_destination</span><span class="plain"> = </span><span class="identifier">MAP_EXIT</span><span class="plain">(</span><span class="identifier">origin</span><span class="plain">, </span><span class="identifier">dir_num</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">immediate_destination</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Spatial::object_is_a_room</span><span class="plain">(</span><span class="identifier">immediate_destination</span><span class="plain">))</span>
|
|
<span class="identifier">ultimate_destination</span><span class="plain"> = </span><span class="identifier">immediate_destination</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Map::object_is_a_door</span><span class="plain">(</span><span class="identifier">immediate_destination</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">via</span><span class="plain">) *</span><span class="identifier">via</span><span class="plain"> = </span><span class="identifier">immediate_destination</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">B</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::Map::get_door_data</span><span class="plain">(</span><span class="identifier">immediate_destination</span><span class="plain">, &</span><span class="identifier">A</span><span class="plain">, &</span><span class="identifier">B</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">A</span><span class="plain"> == </span><span class="identifier">origin</span><span class="plain">) </span><span class="identifier">ultimate_destination</span><span class="plain"> = </span><span class="identifier">B</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> == </span><span class="identifier">origin</span><span class="plain">) </span><span class="identifier">ultimate_destination</span><span class="plain"> = </span><span class="identifier">A</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">ultimate_destination</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">origin</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir_num</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">via</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain"><</span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">story_dir_to_page_dir</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == </span><span class="identifier">dir_num</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">origin</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">via</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="reserved">return</span><span class="plain"> </span><span class="identifier">I</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::room_exit is used in <a href="#SP10">§10</a>, <a href="#SP43_3">§43.3</a>, <a href="#SP45">§45</a>, 3/hm (<a href="3-hm.html#SP1_3">§1.3</a>, <a href="3-hm.html#SP10_2_2">§10.2.2</a>), 3/em (<a href="3-em.html#SP25_6">§25.6</a>, <a href="3-em.html#SP25_6_1">§25.6.1</a>).</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::room_exit_as_indexed is used in <a href="#SP8_17">§8.17</a>, <a href="#SP8_17_1">§8.17.1</a>, <a href="#SP8_17_1_1">§8.17.1.1</a>, <a href="#SP8_17_1_3">§8.17.1.3</a>, <a href="#SP8_17_1_4">§8.17.1.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17"></a><b>§8.17. </b>In practice, the map itself isn't the ideal source of data. It's slow to
|
|
keep checking all of that business with doors, and in any case the map is
|
|
asymmetrical. Instead, we use the following. The tricky point here is that
|
|
we want to record a sort of symmetric version of the map, which takes some
|
|
adjudication.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">As can be seen, step (1) runs in O(R) time, where R is the number of rooms.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(1) Create the spatial relationship arrays</span> <span class="cwebmacronumber">8.17</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>spatial_relationship</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">) </span><<span class="cwebmacro">Consider this Inform map connection for a spatial relationship</span> <span class="cwebmacronumber">8.17.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17_1"></a><b>§8.17.1. </b>We first find a spread of nearly opposite directions: for instance, if <code class="display"><span class="extract">i</span></code>
|
|
is northeast, then <code class="display"><span class="extract">back</span></code> is SW, <code class="display"><span class="extract">cw</span></code> is W, <code class="display"><span class="extract">cwcw</span></code> is NW, <code class="display"><span class="extract">ccw</span></code> is S, <code class="display"><span class="extract">ccwccw</span></code>
|
|
is SE. We also find the <code class="display"><span class="extract">backstep</span></code>, the room you get to if trying to go back
|
|
from the destination in the <code class="display"><span class="extract">back</span></code> direction; which in a nicely arranged
|
|
map will be the room you start from, but that can't be assumed.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The cases below don't exhaust the possibilities. We could be left with a
|
|
1-way connection blocked at the other end, in cases where no 2-way
|
|
connection exists between rooms <code class="display"><span class="extract">R</span></code> and <code class="display"><span class="extract">T</span></code>. If so, we shrug and ignore it;
|
|
this will be a situation where the connection doesn't help us. (It will still
|
|
be plotted on the index page; we just won't use it in our choice of how to
|
|
position the rooms.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Consider this Inform map connection for a spatial relationship</span> <span class="cwebmacronumber">8.17.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">back</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cw</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::rotate_direction</span><span class="plain">(</span><span class="identifier">back</span><span class="plain">, 1); </span> <span class="comment">clockwise one place</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cwcw</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::rotate_direction</span><span class="plain">(</span><span class="identifier">cw</span><span class="plain">, 1); </span> <span class="comment">clockwise twice</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ccw</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::rotate_direction</span><span class="plain">(</span><span class="identifier">back</span><span class="plain">, -1); </span> <span class="comment">counterclockwise once</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ccwccw</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::rotate_direction</span><span class="plain">(</span><span class="identifier">ccw</span><span class="plain">, -1); </span> <span class="comment">counterclockwise twice</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">backstep</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">back</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
|
|
<<span class="cwebmacro">Average out a pair of 2-way connections which each bend</span> <span class="cwebmacronumber">8.17.1.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Turn a straightforward 2-way connection into a spatial relationship</span> <span class="cwebmacronumber">8.17.1.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Average out a pair of 1-way connections which suggest a deformed 2-way connection</span> <span class="cwebmacronumber">8.17.1.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Treat a 1-way connection as 2-way if there are no 2-way connections already</span> <span class="cwebmacronumber">8.17.1.4</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_17">§8.17</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17_1_1"></a><b>§8.17.1.1. </b>What we're looking for here is a configuration like:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Alpha is east of Beta. Beta is south of Alpha.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">This in fact sets up four connections: A is both S and W of B, and B is both
|
|
N and E of A. A reasonable interpretation is that A lies SW of B, and so we
|
|
form a single (symmetric) spatial relationship between them, in this direction.
|
|
We check first clockwise, then counterclockwise.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Average out a pair of 2-way connections which each bend</span> <span class="cwebmacronumber">8.17.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">backstep</span><span class="plain"> == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">cwcw</span><span class="plain"> >= 0) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">cwcw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">cw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cwcw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">T</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cw</span><span class="plain">), </span><span class="identifier">T</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">backstep</span><span class="plain"> == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">ccwccw</span><span class="plain"> >= 0) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">ccwccw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">ccw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccwccw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">T</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccw</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_17_1">§8.17.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17_1_2"></a><b>§8.17.1.2. </b>The easiest case:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Turn a straightforward 2-way connection into a spatial relationship</span> <span class="cwebmacronumber">8.17.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">backstep</span><span class="plain"> == </span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_17_1">§8.17.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17_1_3"></a><b>§8.17.1.3. </b>Now perhaps A runs east to B, B runs south to A, but these are both 1-way
|
|
connections. We'll regard this as being a single passageway running on average
|
|
northeast from A to B:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Average out a pair of 1-way connections which suggest a deformed 2-way connection</span> <span class="cwebmacronumber">8.17.1.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="comment">a deformed 2-way connection made up of 1-way connections</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">cwcw</span><span class="plain"> >= 0) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">cwcw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">cw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cwcw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">T</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">cw</span><span class="plain">), </span><span class="identifier">T</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">ccwccw</span><span class="plain"> >= 0) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">ccwccw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">ccw</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccwccw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">T</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccw</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">ccw</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_17_1">§8.17.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_17_1_4"></a><b>§8.17.1.4. </b>Most of the time, a 1-way connection is fine for mapping purposes; it
|
|
establishes as good a spatial relationship as a 2-way one. But we suppress
|
|
this if either (a) there are already 2-way connections between the rooms
|
|
in general, or (b) the opposite connection exists but is to a different
|
|
room (the case where <code class="display"><span class="extract">backstep</span></code> is not null here).
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Treat a 1-way connection as 2-way if there are no 2-way connections already</span> <span class="cwebmacronumber">8.17.1.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">two_ways</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">R</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::room_exit_as_indexed</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">), </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">T</span><span class="plain">))</span>
|
|
<span class="identifier">two_ways</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">two_ways</span><span class="plain"> == 0) && (</span><span class="identifier">backstep</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">))</span>
|
|
<span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_17_1">§8.17.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. </b>The following ensures that SR links are always symmetric, in opposed
|
|
pairs of directions:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::form_spatial_relationship</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>spatial_relationship</span><span class="plain">[</span><span class="identifier">dir</span><span class="plain">] = </span><span class="identifier">T</span><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-</span><span class="element">>spatial_relationship</span><span class="plain">[</span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">)] = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::form_spatial_relationship is used in <a href="#SP8_17_1_1">§8.17.1.1</a>, <a href="#SP8_17_1_2">§8.17.1.2</a>, <a href="#SP8_17_1_3">§8.17.1.3</a>, <a href="#SP8_17_1_4">§8.17.1.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>The spatial relationships arrays are read only by the following. Note
|
|
that <code class="display"><span class="extract">PL::SpatialMap::read_smap</span></code> suppresses relationships between different submaps (at
|
|
least once the initial map components have been set up). This is done to
|
|
make it easy and quick to cut up a submap into two sub-submaps; effectively
|
|
severing any links between them. All we need do is move the rooms around
|
|
from one submap to another.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><code class="display"><span class="extract">PL::SpatialMap::read_smap_cross</span></code> has the ability to read relationships which cross submap
|
|
boundaries, and will be needed when we place submaps on the global grid.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</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">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to read smap at null room"</span><span class="plain">);</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain">++;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">)-</span><span class="element">>spatial_relationship</span><span class="plain">[</span><span class="identifier">dir</span><span class="plain">];</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">partitioned_into_components</span><span class="plain">) && (</span><span class="identifier">to</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> != </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">))</span>
|
|
<span class="identifier">to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::read_smap_cross</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</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">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to read smap at null room"</span><span class="plain">);</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain">++;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::read_smap is used in <a href="#SP8_25">§8.25</a>, <a href="#SP17">§17</a>, <a href="#SP21">§21</a>, <a href="#SP22">§22</a>, <a href="#SP25">§25</a>, <a href="#SP27">§27</a>, <a href="#SP29">§29</a>, <a href="#SP32_1">§32.1</a>, <a href="#SP33">§33</a>, <a href="#SP34_1">§34.1</a>, <a href="#SP35">§35</a>, <a href="#SP36">§36</a>, <a href="#SP37">§37</a>, <a href="#SP8_30">§8.30</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::read_smap_cross is used in <a href="#SP42">§42</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>While we're at it:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</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">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to read slock at null room"</span><span class="plain">);</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain">++;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">)-</span><span class="element">>lock_exits</span><span class="plain">[</span><span class="identifier">dir</span><span class="plain">];</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::read_slock is used in <a href="#SP8_25">§8.25</a>, <a href="#SP8_27">§8.27</a>, <a href="#SP25">§25</a>, <a href="#SP25_2_3_2">§25.2.3.2</a>, <a href="#SP27">§27</a>, <a href="#SP29">§29</a>, <a href="#SP36">§36</a>, <a href="#SP8_30">§8.30</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. Submap construction. </b>Here's an empty submap, with no rooms.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="functiontext">PL::SpatialMap::new_submap</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain">);</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::new_submap is used in <a href="#SP8_25">§8.25</a>, <a href="#SP23_1_3">§23.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>Doctrinally, a room is always in just one submap, except at the very beginning
|
|
when we are forming the original components into submaps, when most of the
|
|
rooms aren't yet in any submap. Doctrinally, too, if a room is in a submap,
|
|
any room locked to it must always be in the same submap.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">That makes the following routine dangerous to use, since it doesn't guarantee
|
|
either of those things. Use with care.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Because we keep a double-ended linked list to hold membership, adding a
|
|
room to a submap takes constant time with respect to the number of rooms R.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain">)-</span><span class="element">>next_room_in_submap</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>next_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), 1);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::add_room_to_submap is used in <a href="#SP8_22">§8.22</a>, <a href="#SP8_23">§8.23</a>, <a href="#SP8_25">§8.25</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. </b>Here is how we read from the incidence cache. Its purpose is to provide
|
|
a constant running-time way to find out if a given position would collide
|
|
with that of an existing room in the submap — something we could otherwise
|
|
find out only by an O(R) search. If we had to maintain enormous submaps
|
|
of rooms, we'd probably want a balanced geographical tree structure, of the
|
|
sort used for collision detection in first-person shooters; but as it is,
|
|
we have plenty of memory and relatively few possible location coordinate
|
|
positions. So we simply keep a cubical array; though it may need to be
|
|
resized as the rooms in the submap move around, which complicates things.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Anyway, this returns the number of rooms at position P within the submap.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::occupied_in_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_index</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> < 0) </span><span class="reserved">return</span><span class="plain"> 0;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::occupied_in_submap is used in <a href="#SP21">§21</a>, <a href="#SP8_31">§8.31</a>, <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. </b>The cache will be invalidated by any movement of a room, so the following
|
|
routine must be notified of any such:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::move_room_within_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">O</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">, -1);</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">, 1);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::move_room_within_submap is used in <a href="#SP8_2">§8.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>Here goes, then: the following increments the cached population value at <code class="display"><span class="extract">P</span></code>
|
|
if <code class="display"><span class="extract">m</span></code> is 1, decrements it if -1.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::add_room_to_cache</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">m</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Geometry::within_cuboid</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Location P lies outside the current incidence cache</span> <span class="cwebmacronumber">16.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_index</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</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">t</span><span class="plain">+</span><span class="identifier">m</span><span class="plain"> < 0) </span><span class="identifier">t</span><span class="plain"> = -</span><span class="identifier">m</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">t</span><span class="plain">+</span><span class="identifier">m</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain"> == 1) </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain"> += 2*</span><span class="identifier">t</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain"> == -1) </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain"> -= 2*(</span><span class="identifier">t</span><span class="plain">-1);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::add_room_to_cache is used in <a href="#SP13">§13</a>, <a href="#SP15">§15</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16_1"></a><b>§16.1. </b>We make a new incidence cache which is more than large enough to contain
|
|
both P and the existing one, and then copy the old one's contents into the
|
|
new one before deallocating the old.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This looks as if it has cubic running time, but isn't really that bad,
|
|
since the volume of the cuboid is probably about proportional to R rather
|
|
than R^3 (assuming rooms are fairly evenly distributed through space).
|
|
Still, we ought to make sure it happens fairly seldom. We therefore expand
|
|
the cuboid by a margin giving us always at least 20 more cells than we need
|
|
horizontally, and 3 vertically. Since movements within submaps are modest
|
|
and local, this means very few submaps need to expand more than twice at
|
|
the most.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Location P lies outside the current incidence cache</span> <span class="cwebmacronumber">16.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">old_cuboid</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain">;</span>
|
|
<span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">new_cuboid</span><span class="plain"> = </span><span class="identifier">old_cuboid</span><span class="plain">;</span>
|
|
<span class="functiontext">Geometry::thicken_cuboid</span><span class="plain">(&</span><span class="identifier">new_cuboid</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">, </span><span class="functiontext">Geometry::vec</span><span class="plain">(20, 20, 3));</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">extent</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_volume</span><span class="plain">(</span><span class="identifier">new_cuboid</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">new_cache</span><span class="plain"> = </span><span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">extent</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">int</span><span class="plain">), </span><span class="identifier">MAP_INDEX_MREASON</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">x</span><span class="plain">, </span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">z</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> = </span><span class="identifier">new_cuboid</span><span class="element">.corner0.x</span><span class="plain">; </span><span class="identifier">x</span><span class="plain"> <= </span><span class="identifier">new_cuboid</span><span class="element">.corner1.x</span><span class="plain">; </span><span class="identifier">x</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">y</span><span class="plain"> = </span><span class="identifier">new_cuboid</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">; </span><span class="identifier">y</span><span class="plain"> <= </span><span class="identifier">new_cuboid</span><span class="element">.corner1</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">; </span><span class="identifier">y</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">z</span><span class="plain"> = </span><span class="identifier">new_cuboid</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">; </span><span class="identifier">z</span><span class="plain"> <= </span><span class="identifier">new_cuboid</span><span class="element">.corner1</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">; </span><span class="identifier">z</span><span class="plain">++) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_index</span><span class="plain">(</span><span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x</span><span class="plain">,</span><span class="identifier">y</span><span class="plain">,</span><span class="identifier">z</span><span class="plain">), </span><span class="identifier">new_cuboid</span><span class="plain">);</span>
|
|
<span class="identifier">new_cache</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 0;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">old_cache</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">old_cache</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> = </span><span class="identifier">old_cuboid</span><span class="element">.corner0.x</span><span class="plain">; </span><span class="identifier">x</span><span class="plain"> <= </span><span class="identifier">old_cuboid</span><span class="element">.corner1.x</span><span class="plain">; </span><span class="identifier">x</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">y</span><span class="plain"> = </span><span class="identifier">old_cuboid</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">; </span><span class="identifier">y</span><span class="plain"> <= </span><span class="identifier">old_cuboid</span><span class="element">.corner1</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">; </span><span class="identifier">y</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">z</span><span class="plain"> = </span><span class="identifier">old_cuboid</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">; </span><span class="identifier">z</span><span class="plain"> <= </span><span class="identifier">old_cuboid</span><span class="element">.corner1</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">; </span><span class="identifier">z</span><span class="plain">++) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_index</span><span class="plain">(</span><span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x</span><span class="plain">,</span><span class="identifier">y</span><span class="plain">,</span><span class="identifier">z</span><span class="plain">), </span><span class="identifier">old_cuboid</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="identifier">old_cache</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">t</span><span class="plain"> > 0) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="functiontext">Geometry::cuboid_index</span><span class="plain">(</span><span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x</span><span class="plain">,</span><span class="identifier">y</span><span class="plain">,</span><span class="identifier">z</span><span class="plain">), </span><span class="identifier">new_cuboid</span><span class="plain">);</span>
|
|
<span class="identifier">new_cache</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">t</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::free_incidence_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain"> = </span><span class="identifier">new_cache</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_size</span><span class="plain"> = </span><span class="identifier">extent</span><span class="plain">*((</span><span class="reserved">int</span><span class="plain">) </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">int</span><span class="plain">));</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain"> = </span><span class="identifier">new_cuboid</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP16">§16</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_18"></a><b>§8.18. </b>Here we throw away the cache, something which must otherwise only be done
|
|
when the submap has no rooms...
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::free_incidence_cache</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="identifier">Memory::I7_free</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain">, </span><span class="identifier">MAP_INDEX_MREASON</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_size</span><span class="plain">);</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::free_incidence_cache is used in <a href="#SP16_1">§16.1</a>, <a href="#SP8_19">§8.19</a>, <a href="#SP8_20">§8.20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_19"></a><b>§8.19. </b>...such as now:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::empty_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>last_room_in_submap</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::free_incidence_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain"> = 0;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::empty_submap is used in <a href="#SP8_22">§8.22</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_20"></a><b>§8.20. </b>And finally:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::destroy_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::free_incidence_cache</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">DESTROY</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::destroy_submap is used in <a href="#SP23_1_3">§23.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_21"></a><b>§8.21. </b>Suppose we want to move all the rooms in a submap at once, and all by the
|
|
same vector <code class="display"><span class="extract">D</span></code>. Then we can simply move the cache boundaries, too, and not
|
|
have to change the contents of the cache at all.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position_breaking_cache</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="functiontext">Geometry::cuboid_translate</span><span class="plain">(&(</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds</span><span class="plain">), </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="functiontext">Geometry::cuboid_translate</span><span class="plain">(&(</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>incidence_cache_bounds</span><span class="plain">), </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::move_component is used in <a href="#SP8_32_1_1">§8.32.1.1</a>, <a href="#SP8_32_1_2">§8.32.1.2</a>, <a href="#SP8_32_1_3">§8.32.1.3</a>, <a href="#SP8_32_1_3_1">§8.32.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_22"></a><b>§8.22. </b>The following routines will be used in order to divide an existing submap
|
|
into two new ones, which we'll call Zone 1 and Zone 2, and then to merge
|
|
them back again.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We start with each room in <code class="display"><span class="extract">sub</span></code> having a value of <code class="display"><span class="extract">zone</span></code> set to either
|
|
<code class="display"><span class="extract">Z1_number</span></code> or <code class="display"><span class="extract">Z2_number</span></code>, the former meaning it is destined for Zone 1,
|
|
the latter for Zone 2. It's assumed here that if two rooms are locked together
|
|
then they have the same value of <code class="display"><span class="extract">zone</span></code>. With that done, we empty <code class="display"><span class="extract">sub</span></code>,
|
|
since its rooms have all moved out.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::create_submaps_from_zones</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z2_number</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone2</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z1_number</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">Zone1</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">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z2_number</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">Zone2</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::empty_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::create_submaps_from_zones is used in <a href="#SP23_1_3">§23.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_23"></a><b>§8.23. </b>Convert membership of Zone 1 or 2 back into value of the zone number: the
|
|
reverse process exactly.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::create_zones_from_submaps</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z2_number</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone2</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">Zone1</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z1_number</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">Zone2</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z2_number</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::create_zones_from_submaps is used in <a href="#SP23_1_3">§23.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_24"></a><b>§8.24. Partitioning to component submaps. </b>We can now go back to our strategy. The next task is to partition the map into
|
|
components, that is, equivalence classes under the closure of the relation
|
|
R~ S if either R is locked to S or if there is a spatial relationship
|
|
between R and S.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We ensure that the first-created component is the one containing the
|
|
benchmark room.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(2) Partition the set of rooms into component submaps</span> <span class="cwebmacronumber">8.24</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">PL::SpatialMap::create_map_component_around</span><span class="plain">(</span><span class="identifier">benchmark_room</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::create_map_component_around</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_25"></a><b>§8.25. </b>The following grows a component outwards from <code class="display"><span class="extract">at</span></code>, so that it also includes
|
|
all rooms locked to <code class="display"><span class="extract">at</span></code> or with a SR to it. If <code class="display"><span class="extract">at</span></code> is currently not in a
|
|
component, we start a new submap to hold it.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that <code class="display"><span class="extract">PL::SpatialMap::create_map_component_around</span></code> has constant running time, i.e., it
|
|
doesn't depend on R, the number of rooms. It is called exactly once for
|
|
each room, so phase (2) has running time O(R).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::create_map_component_around</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::new_submap</span><span class="plain">());</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">locked_to</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">locked_to</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">locked_to</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> != </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">locked_to</span><span class="plain">, </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::create_map_component_around</span><span class="plain">(</span><span class="identifier">locked_to</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">dest</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">dest</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">dest</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> != </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">)) {</span>
|
|
<span class="functiontext">PL::SpatialMap::add_room_to_submap</span><span class="plain">(</span><span class="identifier">dest</span><span class="plain">, </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::create_map_component_around</span><span class="plain">(</span><span class="identifier">dest</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::create_map_component_around is used in <a href="#SP8_24">§8.24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_26"></a><b>§8.26. Movements of single rooms. </b>Positions are just 3-vectors, so:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::translate_room</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::move_room_to</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::move_anything_locked_to</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::translate_room is used in <a href="#SP23_1_4_1">§23.1.4.1</a>, <a href="#SP35_1">§35.1</a>, <a href="#SP37_1_1">§37.1.1</a>, <a href="#SP8_35">§8.35</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::move_room_to is used in <a href="#SP33">§33</a>, <a href="#SP8_31">§8.31</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_27"></a><b>§8.27. Synchronising movements of locked rooms. </b>The next preliminary we need is the implementation of locking. As we've seen,
|
|
the source text can instruct us to lock one room so that it lies perfectly
|
|
placed with respect to another (in the sense that if there were an exit
|
|
between them in that direction then it would have heat 0).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The following is for use after room R has been moved to a new grid position;
|
|
it moves anything locked to R (and anything locked to that, and so on) to
|
|
corresponding positions.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::move_anything_locked_to</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R2</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-></span><span class="identifier">shifted</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::move_anything_locked_to_r</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::move_anything_locked_to_r</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">shifted</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">shifted</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">R</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">F</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="functiontext">PL::SpatialMap::move_anything_locked_to_r</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::move_anything_locked_to is used in <a href="#SP8_26">§8.26</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::move_anything_locked_to_r is used in <a href="#SP8_28">§8.28</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_28"></a><b>§8.28. </b>That allows us to define the initial state of placements in a submap.
|
|
All rooms begin at (0,0,0), except that locking may offset a few of them
|
|
slightly. This runs in O(R) time.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::lock_positions_in_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">shifted</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::move_anything_locked_to_r</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::lock_positions_in_submap is used in <a href="#SP8_29">§8.29</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_29"></a><b>§8.29. Positioning within components. </b>This is much more difficult. It's going to be a matter of minimising the
|
|
badness of the configuration, but to talk about it it's convenient to have
|
|
a better word than "badness". So the "heat" is a penalty score
|
|
calculated at each map connection which keeps track of the badness of local
|
|
geometric distortion; thus, lowering the temperature improves the geometry.
|
|
We want to reduce the total amount of heat, ideally to absolute zero, but
|
|
we also to want to avoid hot-spots.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The worst case for running time here is when the entire map is a single component;
|
|
the loop over submaps doesn't therefore add to the running time.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(3) Position the rooms within each component</span> <span class="cwebmacronumber">8.29</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">total_accuracy</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Laying out component %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::lock_positions_in_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">); </span> <span class="comment">O(R) running time</span>
|
|
<span class="functiontext">PL::SpatialMap::establish_natural_lengths</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">); </span> <span class="comment">O(R) running time</span>
|
|
<span class="functiontext">PL::SpatialMap::position_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">total_accuracy</span><span class="plain"> += </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Component %d has final heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">All components laid out: total heat %d\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">total_accuracy</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: cutpoint choosing %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">cutpoint_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: dividing %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">division_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: sliding %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">slide_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: cooling %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">cooling_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: quenching %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">quenching_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: diffusion %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">diffusion_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: radiation %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">radiation_spending</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cost: explosion %d drognas\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">explosion_spending</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. </b>Every spatial relationship has a "length", which is a positive integer.
|
|
This is our preferred amount of stretch when laying out the rooms; a
|
|
length of 1 means one grid increment, and that's our preference if we
|
|
can have it. Initially, all SRs have length 1.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::establish_natural_lengths</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</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="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">))</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 1;</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::establish_natural_lengths is used in <a href="#SP8_29">§8.29</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. Heat. </b>Before we can get any further with (3), we need to be able to measure heat. For
|
|
a submap, it's the sum of its room heats, plus additional heat (and a
|
|
lot of it) for each pair of rooms occupying the same grid location. We also
|
|
refresh the cached value of the smallest squarely oriented cuboid which
|
|
contains the component.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The mapmaker behaves slowly if the collision heat penalty is low enough
|
|
that large amounts of heat soaked up from ordinary exits can ever exceed it.
|
|
On the other hand, for very large maps with horrible tangles the total number
|
|
of collisions can be enormous, and quite high heats are observed; I've seen
|
|
temperatures over 165,000,000, so temperatures of 1,000,000,000 are not at
|
|
all out of the question. So we will be careful, just on the safe side,
|
|
not to overflow a single <code class="display"><span class="extract">int</span></code>; we'll cap temperatures except to add a tiny
|
|
extra heat so that there is still a slight incentive to remove collisions
|
|
even in submaps at this unthinkably hot level.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The FHM magazine website informs me that the current (2010) maximal value of
|
|
temperature is <code class="display"><span class="extract">CHERYL_COLE</span></code>, but I think I'll call it <code class="display"><span class="extract">FUSION_POINT</span></code>.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">OVERLYING_HEAT</span><span class="plain"> 20</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">COLLISION_HEAT</span><span class="plain"> 50000</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">FUSION_POINT</span><span class="plain"> 1000000000</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">h1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">h2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">h1</span><span class="plain">+</span><span class="identifier">h2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain"> > </span><span class="constant">FUSION_POINT</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FUSION_POINT</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::heat_sum is used in <a href="#SP19">§19</a>, <a href="#SP42">§42</a>, <a href="#SP42_1">§42.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. </b>Finding the heat of a submap runs in O(S) time, where S is the number
|
|
of rooms in the submap; this is the point of having the incidence cache,
|
|
without which it would be O(S^2). Even so, we will try to make S a lot
|
|
smaller than R.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(</span><span class="identifier">heat</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_room_heat</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">));</span>
|
|
<span class="functiontext">Geometry::adjust_cuboid</span><span class="plain">(&(</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">collisions</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain">;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">collisions</span><span class="plain"> >= 1000) {</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(</span><span class="identifier">heat</span><span class="plain">, 1000*</span><span class="constant">COLLISION_HEAT</span><span class="plain">);</span>
|
|
<span class="identifier">collisions</span><span class="plain"> -= 1000;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(</span><span class="identifier">heat</span><span class="plain">, </span><span class="identifier">collisions</span><span class="plain">*</span><span class="constant">COLLISION_HEAT</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain"> == </span><span class="constant">FUSION_POINT</span><span class="plain">) </span><span class="identifier">heat</span><span class="plain"> = </span><span class="constant">FUSION_POINT</span><span class="plain"> + </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>superpositions</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> = </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_submap_heat is used in <a href="#SP23">§23</a>, <a href="#SP23_1">§23.1</a>, <a href="#SP23_1_1">§23.1.1</a>, <a href="#SP23_1_4">§23.1.4</a>, <a href="#SP31">§31</a>, <a href="#SP34">§34</a>, <a href="#SP34_1">§34.1</a>, <a href="#SP35">§35</a>, <a href="#SP35_1">§35.1</a>, <a href="#SP37">§37</a>, <a href="#SP37_1_1">§37.1.1</a>, <a href="#SP8_31">§8.31</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. </b>The total heat for a room is in turn the sum of its exit heats. This runs
|
|
in constant time.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_room_heat</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">h</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) </span><span class="identifier">h</span><span class="plain"> += </span><span class="functiontext">PL::SpatialMap::find_exit_heat</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_room_heat is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b>So now we come to it: measuring the heat of an exit, which is a matter of
|
|
how much geometric distortion it has in the current layout. This is based
|
|
primarily on the angular divergence in direction between the known exit
|
|
direction and the grid direction, and only secondarily on distance
|
|
anomalies, because when the user typed "the Field is east of the River"
|
|
no particular distance was implied. As with Harry Beck's London Underground
|
|
map (1931), we may be constrained to use only about eight possible angles but
|
|
nevertheless care more about angle than length.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that an exit in the lattice (i.e., not IN or OUT) which joins two
|
|
different rooms can only have heat 0 if the destination room lies exactly
|
|
at the optimal grid offset from the origin room. (In the sense that you'd
|
|
expect the room north from (0,0,0) to be at (0,1,0), and so on.) A
|
|
component therefore has a total heat of 0 if and only if it has been
|
|
aligned perfectly on a grid such that all exits are optimal.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This too runs in constant time.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">ANGULAR_MULTIPLIER</span><span class="plain"> 50</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_exit_heat</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit</span><span class="plain">) {</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain">++;</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">exit</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">if there's no exit this way, there's no heat</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">an exit from a room to itself doesn't show on the map</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::direction_is_along_lattice</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">IN, OUT generate no heat</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">));</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">, </span><span class="identifier">Zero_vector</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">COLLISION_HEAT</span><span class="plain">; </span> <span class="comment">the two rooms have collided!</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">distance_distortion</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_length_squared</span><span class="plain">(</span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">distance_distortion</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain"> 0; </span> <span class="comment">perfect placement</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">angular_distortion</span><span class="plain"> = (</span><span class="reserved">int</span><span class="plain">) (</span><span class="constant">ANGULAR_MULTIPLIER</span><span class="plain">*</span><span class="functiontext">Geometry::vec_angular_separation</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">overlying_penalty</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">angular_distortion</span><span class="plain"> == 0) && (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">Zero_vector</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
|
|
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">n</span><span class="plain">++ < 20) && (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::occupied_in_submap</span><span class="plain">(</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">, </span><span class="identifier">P</span><span class="plain">) > 0)</span>
|
|
<span class="identifier">overlying_penalty</span><span class="plain"> += </span><span class="constant">OVERLYING_HEAT</span><span class="plain">;</span>
|
|
<span class="identifier">P</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">angular_distortion</span><span class="plain"> + </span><span class="identifier">distance_distortion</span><span class="plain"> + </span><span class="identifier">overlying_penalty</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_exit_heat is used in <a href="#SP20">§20</a>, <a href="#SP32_1">§32.1</a>, <a href="#SP34">§34</a>, <a href="#SP36">§36</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. </b>The following simply tests whether a link is correctly aligned, in that
|
|
the destination room lies along a multiple of the exit vector from the
|
|
origin. In effect, it tests whether <code class="display"><span class="extract">angular_distortion</span></code> is zero.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::exit_aligned</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit</span><span class="plain">) {</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain">++;</span>
|
|
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">exit</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">at any rate, not misaligned</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">to</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">ditto</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::direction_is_along_lattice</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">IN, OUT are always aligned</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">, </span><span class="identifier">Zero_vector</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; </span> <span class="comment">bad, but not for alignment reasons</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">angular_distortion</span><span class="plain"> = (</span><span class="reserved">int</span><span class="plain">) (</span><span class="constant">ANGULAR_MULTIPLIER</span><span class="plain">*</span><span class="functiontext">Geometry::vec_angular_separation</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">angular_distortion</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::exit_aligned is used in <a href="#SP37">§37</a>, <a href="#SP37_1">§37.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. Subdividing our submap. </b>Any remotely good algorithm for this task will have a dangerous running time
|
|
if let loose on the entire map, and in any case, the entirety may have such
|
|
a complex layout that it defeats our tactics. So we need a divide-and-rule
|
|
method; one which cuts the map into two pieces, positions each piece, and
|
|
then glues them back together again.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We will eventually use five tactics: cooling, quenching, diffusion,
|
|
radiation and explosion. Cooling is quick and useful, so we'll try that
|
|
first even before looking for subdivisions.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">unique_Z_number</span><span class="plain"> = 1;</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::position_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">POSITIONING submap %d: initial heat %d"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> == 0) </span><span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">": nothing to do"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Log::aspect_switched_on</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_DA</span><span class="plain">)) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">n</span><span class="plain">++) % 8 == 0) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string"> "</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">" $O"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::cool_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> > 0) {</span>
|
|
<<span class="cwebmacro">Attempt to divide the current submap in two</span> <span class="cwebmacronumber">23.1</span>><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">POSITIONING submap %d done: cooled by %d to %d "</span>
|
|
<span class="string">"at cost of %d drognas\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">,</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::position_submap is used in <a href="#SP8_29">§8.29</a>, <a href="#SP23_1_3">§23.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1"></a><b>§23.1. </b>We will look for a way to divide the rooms up into two subsets, allocating
|
|
each subset a unique zone number. (We must remember that all of this code is
|
|
running recursively.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">There are three cases: sometimes the <code class="display"><span class="extract">PL::SpatialMap::work_out_optimal_cutpoint</span></code> function
|
|
recommends cutting a single spatial relationship, from <code class="display"><span class="extract">div_F1</span></code> to <code class="display"><span class="extract">div_T1</span></code>,
|
|
and sometimes it recommends cutting a pair. Then again, sometimes it finds
|
|
no good cutpoint.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Attempt to divide the current submap in two</span> <span class="cwebmacronumber">23.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1_number</span><span class="plain"> = </span><span class="identifier">unique_Z_number</span><span class="plain">++, </span><span class="identifier">Z2_number</span><span class="plain"> = </span><span class="identifier">unique_Z_number</span><span class="plain">++;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">div_F1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">div_T1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">div_dir1</span><span class="plain"> = -1;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">div_F2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">div_T2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">div_dir2</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">found</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::work_out_optimal_cutpoint</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, &</span><span class="identifier">div_F1</span><span class="plain">, &</span><span class="identifier">div_T1</span><span class="plain">, &</span><span class="identifier">div_dir1</span><span class="plain">,</span>
|
|
<span class="plain">&</span><span class="identifier">div_F2</span><span class="plain">, &</span><span class="identifier">div_T2</span><span class="plain">, &</span><span class="identifier">div_dir2</span><span class="plain">);</span>
|
|
<span class="identifier">cutpoint_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">found</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Set the zone numbers throughout the two soon-to-be zones</span> <span class="cwebmacronumber">23.1.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Divide the submap into zones, recurse to position those, then merge back</span> <span class="cwebmacronumber">23.1.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Slide the two former zones together along the F1-to-T1 line, minimising heat</span> <span class="cwebmacronumber">23.1.4</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) </span><span class="functiontext">PL::SpatialMap::radiate_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span>
|
|
<<span class="cwebmacro">Position this indivisible component</span> <span class="cwebmacronumber">23.1.1</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23">§23</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1_1"></a><b>§23.1.1. </b>When we can't divide, we use our remaining three tactics, stopping if the
|
|
submap should reach absolute zero:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Position this indivisible component</span> <span class="cwebmacronumber">23.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::quench_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::diffuse_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::quench_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::radiate_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) >= </span><span class="constant">COLLISION_HEAT</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::explode_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23_1">§23.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1_2"></a><b>§23.1.2. </b>Supposing we can divide, though, we need to set zone numbers throughout
|
|
the submap, and the procedure is different depending on whether we're
|
|
dividing at one relationship F1-to-T1 or at two, F1-to-T1 and F2-to-T2.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Set the zone numbers throughout the two soon-to-be zones</span> <span class="cwebmacronumber">23.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1_count</span><span class="plain"> = 0, </span><span class="identifier">Z2_count</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">div_F2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">predivision_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_twocut</span><span class="plain">(</span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">div_T1</span><span class="plain">, </span><span class="identifier">div_F2</span><span class="plain">, </span><span class="identifier">div_T2</span><span class="plain">, </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="identifier">Z2_number</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z1_number</span><span class="plain">) </span><span class="identifier">Z1_count</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z2_number</span><span class="plain">) </span><span class="identifier">Z2_count</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Making a double cut: $O %s to $O and $O %s to $O at cost %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">div_F1</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">div_dir1</span><span class="plain">), </span><span class="identifier">div_T1</span><span class="plain">,</span>
|
|
<span class="identifier">div_F2</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">div_dir2</span><span class="plain">), </span><span class="identifier">div_T2</span><span class="plain">,</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">predivision_spending</span><span class="plain">);</span>
|
|
<span class="identifier">division_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">predivision_spending</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">predivision_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_onecut</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">div_T1</span><span class="plain">,</span>
|
|
<span class="plain">&</span><span class="identifier">Z1_count</span><span class="plain">, &</span><span class="identifier">Z2_count</span><span class="plain">, </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="identifier">Z2_number</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Making a single cut: $O %s to $O at cost %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">div_F1</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">div_dir1</span><span class="plain">), </span><span class="identifier">div_T1</span><span class="plain">,</span>
|
|
<span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">predivision_spending</span><span class="plain">);</span>
|
|
<span class="identifier">division_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">predivision_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"This produces two zones of sizes %d and %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">Z1_count</span><span class="plain">, </span><span class="identifier">Z2_count</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23_1">§23.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1_3"></a><b>§23.1.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Divide the submap into zones, recurse to position those, then merge back</span> <span class="cwebmacronumber">23.1.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone1</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::new_submap</span><span class="plain">();</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">Zone2</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::new_submap</span><span class="plain">();</span>
|
|
<span class="functiontext">PL::SpatialMap::create_submaps_from_zones</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="identifier">Zone1</span><span class="plain">, </span><span class="identifier">Z2_number</span><span class="plain">, </span><span class="identifier">Zone2</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Zone 1 becomes submap %d; zone 2 becomes submap %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">Zone1</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">Zone2</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::position_submap</span><span class="plain">(</span><span class="identifier">Zone1</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::position_submap</span><span class="plain">(</span><span class="identifier">Zone2</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::create_zones_from_submaps</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">Z1_number</span><span class="plain">, </span><span class="identifier">Zone1</span><span class="plain">, </span><span class="identifier">Z2_number</span><span class="plain">, </span><span class="identifier">Zone2</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Destroying submaps %d and %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">Zone1</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">Zone2</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::destroy_submap</span><span class="plain">(</span><span class="identifier">Zone1</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::destroy_submap</span><span class="plain">(</span><span class="identifier">Zone2</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23_1">§23.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1_4"></a><b>§23.1.4. </b>The zone-1 rooms are now correctly placed with respect to each other, and
|
|
vice versa, but we might have a horrendous breakage where the two sets of
|
|
rooms meet. We need to rejoin them, and we do this by stretching the
|
|
F1-to-T1 line segment to that length which minimises the total heat of
|
|
the submap. For a single cut, this is clearly the smallest length such
|
|
that there's no collision between old zone-1 and old zone-2 rooms.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The worst case is a configuration like so:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>X is west of Y. X1 is northeast of X. X2 is northeast of X. Y1 is northwest of Y. Y2 is northwest of Y1.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">We've cut between X and Y. To give clearance so that X2 and Y2 do not collide,
|
|
the new length X to Y needs to be 5.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">However, it's computationally too expensive to check every possible length
|
|
as high as that: it would run in O(S^2) time, and we must remember that
|
|
this is the divide-and-rule code running on even the largest submaps, so
|
|
that this is effectively an O(R^2) algorithm. On a 300-room example source
|
|
text (the entire London Underground map, zones 1 to 7) this results in
|
|
sliding taking up about 80 percent of our time, which is unacceptable.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We therefore cap the length once we have reduced below the collision penalty.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">CAP_ON_SLIDE_LENGTHS</span><span class="plain"> 10</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Slide the two former zones together along the F1-to-T1 line, minimising heat</span> <span class="cwebmacronumber">23.1.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">preslide_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Axis</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">div_dir1</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">worst_case_length</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">worst_case_length</span><span class="plain">++;</span>
|
|
<span class="identifier">worst_case_length</span><span class="plain">--;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">coolest_L</span><span class="plain"> = 1, </span><span class="identifier">coolest_temperature</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> = 1; </span><span class="identifier">L</span><span class="plain"> <= </span><span class="identifier">worst_case_length</span><span class="plain">; </span><span class="identifier">L</span><span class="plain">++) {</span>
|
|
<span class="functiontext">PL::SpatialMap::save_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Displace zone 2 relative to zone 1</span> <span class="cwebmacronumber">23.1.4.1</span>><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">h</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain"> < </span><span class="identifier">coolest_temperature</span><span class="plain">) || (</span><span class="identifier">coolest_temperature</span><span class="plain"> == -1)) {</span>
|
|
<span class="identifier">coolest_temperature</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">coolest_L</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::restore_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">coolest_temperature</span><span class="plain"> >= 0) && (</span><span class="identifier">coolest_temperature</span><span class="plain"> < </span><span class="constant">COLLISION_HEAT</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">L</span><span class="plain"> == </span><span class="constant">CAP_ON_SLIDE_LENGTHS</span><span class="plain">))</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Optimal axis length for cut-exit is %d (heat %d), found at cost %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">coolest_L</span><span class="plain">, </span><span class="identifier">coolest_temperature</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">preslide_spending</span><span class="plain">);</span>
|
|
<span class="identifier">slide_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">preslide_spending</span><span class="plain">;</span>
|
|
<span class="identifier">L</span><span class="plain"> = </span><span class="identifier">coolest_L</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Displace zone 2 relative to zone 1</span> <span class="cwebmacronumber">23.1.4.1</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23_1">§23.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23_1_4_1"></a><b>§23.1.4.1. </b>Here we slide rooms which came from Zone 2 so that they retain their
|
|
positions with respect to each other, and therefore to T1, and so that T1
|
|
is placed correctly aligned along the axis from F1 with length L.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Because there can never be locks across zone boundaries, this process
|
|
can't break a lock between two rooms.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Displace zone 2 relative to zone 1</span> <span class="cwebmacronumber">23.1.4.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">div_dir1</span><span class="plain">] = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span>
|
|
<span class="functiontext">Geometry::vec_scale</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">Axis</span><span class="plain">),</span>
|
|
<span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">div_F1</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">div_T1</span><span class="plain">)));</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">Z2</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">Z2</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">Z2</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z2_number</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::translate_room</span><span class="plain">(</span><span class="identifier">Z2</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP23_1_4">§23.1.4</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. Finding how to divide. </b>That completes the logic for how we divide and conquer the submaps, except,
|
|
of course, that some of the critical steps weren't spelled out. We do that
|
|
now. First, the code to find good cutpoint(s): map connection(s) which, if
|
|
removed, would divide the submap efficiently. We prefer single cuts if
|
|
possible, but can live with double cuts; we want as evenly spread a
|
|
division as possible. (The "spread" is the difference in room count
|
|
of the larger zone compared to the smaller zone; we want to minimise this.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Here is the basic idea. We will recursively spread a generation count out
|
|
into the submap, with the first room (<code class="display"><span class="extract">first</span></code> below) belonging to generation 1.
|
|
We'll use the <code class="display"><span class="extract">zone</span></code> field to store this, since it's an integer attached to
|
|
each room which isn't yet in use. <code class="display"><span class="extract">PL::SpatialMap::assign_generation_count</span></code> is recursively
|
|
called so that it visits each room exactly once, and increases the generation
|
|
on each call. Thus a line of rooms from <code class="display"><span class="extract">first</span></code> would have generations 1, 2,
|
|
3, ... When <code class="display"><span class="extract">PL::SpatialMap::assign_generation_count</span></code> finds a connection from its current
|
|
position to a room with a lower generation, we say that there's a "contact".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">What makes the routine so effective is that it returns a great deal of data
|
|
about the high-spots of the history after it was called. The mechanism for
|
|
this, though, is that the caller has to set up a pile of arrays, and then
|
|
pass pointers to <code class="display"><span class="extract">PL::SpatialMap::assign_generation_count</span></code>; on its exit, the arrays are
|
|
then populated with answers.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This calculation runs in O(S) time, where S is the number of rooms in
|
|
the submap. It's guaranteed to find the optimal single cut, if one exists;
|
|
it's not guaranteed to find the optimal double cut — I suspect this is
|
|
not possible in O(S) running time, though possibly in O(Slog S) — but
|
|
in any case we have heuristic reasons why we don't always want the optimal
|
|
double cut. What can be said is that we at least try to find good spreads,
|
|
usually succeed in practice, and are guaranteed to find at least one double
|
|
cut if any exists.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The guarantees are void in a small number of cases where locks have been
|
|
applied: for instance, if the entire submap is locked together, nothing can
|
|
ever be cut. Should that happen, the user will find that the map-maker may
|
|
run slowly; it's his own fault.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">EXPLORATION_RECORDS</span><span class="plain"> 3 </span> <span class="comment">how much we keep track of</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">BEST_ONECUT_ER</span><span class="plain"> 0 </span> <span class="comment">what's the best-known single link to cut?</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain"> 1 </span> <span class="comment">what's the best-known pair of links equal in direction?</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">BEST_TWOCUT_ER</span><span class="plain"> 2 </span> <span class="comment">and in general?</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">CLIPBOARD_SIZE</span><span class="plain"> 3 </span> <span class="comment">a term to be explained below</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::work_out_optimal_cutpoint</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">way</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">from2</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">to2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">way2</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">first</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">size</span><span class="plain"> = 0;</span>
|
|
|
|
<<span class="cwebmacro">Find the size of and first room in the submap, and give all rooms generation 0</span> <span class="cwebmacronumber">24.1</span>><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">first</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 1;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">best_from1</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">], *</span><span class="identifier">best_to1</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">best_from2</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">], *</span><span class="identifier">best_to2</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">best_dir2</span><span class="plain">[</span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">];</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">outer_contact_generation</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">], </span><span class="identifier">outer_contact_dir</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">outer_contact_from</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">], *</span><span class="identifier">outer_contact_to</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">];</span>
|
|
<<span class="cwebmacro">Initialise all this cutpoint search workspace</span> <span class="cwebmacronumber">24.2</span>><span class="plain">;</span>
|
|
|
|
<span class="functiontext">PL::SpatialMap::assign_generation_count</span><span class="plain">(</span><span class="identifier">first</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">size</span><span class="plain">,</span>
|
|
<span class="identifier">best_spread</span><span class="plain">,</span>
|
|
<span class="identifier">best_from1</span><span class="plain">, </span><span class="identifier">best_to1</span><span class="plain">, </span><span class="identifier">best_dir1</span><span class="plain">,</span>
|
|
<span class="identifier">best_from2</span><span class="plain">, </span><span class="identifier">best_to2</span><span class="plain">, </span><span class="identifier">best_dir2</span><span class="plain">,</span>
|
|
<span class="identifier">outer_contact_generation</span><span class="plain">, </span><span class="identifier">outer_contact_from</span><span class="plain">, </span><span class="identifier">outer_contact_to</span><span class="plain">, </span><span class="identifier">outer_contact_dir</span><span class="plain">);</span>
|
|
|
|
<<span class="cwebmacro">Look at the results and return connections to cut, if any look good enough</span> <span class="cwebmacronumber">24.3</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::work_out_optimal_cutpoint is used in <a href="#SP23_1">§23.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_1"></a><b>§24.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Find the size of and first room in the submap, and give all rooms generation 0</span> <span class="cwebmacronumber">24.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0; </span> <span class="comment">i.e., not yet given a generation</span>
|
|
<span class="identifier">size</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">first</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">size</span><span class="plain"> == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_2"></a><b>§24.2. </b>See below.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Initialise all this cutpoint search workspace</span> <span class="cwebmacronumber">24.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">i</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">outer_contact_generation</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="identifier">outer_contact_from</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">outer_contact_to</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">outer_contact_dir</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> = 0; </span><span class="identifier">i</span><span class="plain"> < </span><span class="constant">EXPLORATION_RECORDS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">best_spread</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">size</span><span class="plain">+1; </span> <span class="comment">an impossibly high value</span>
|
|
<span class="identifier">best_from1</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">best_to1</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="identifier">best_from2</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">best_to2</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">best_dir2</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24_3"></a><b>§24.3. </b>Suppose the larger and smaller zones have sizes X and Y. Then clearly
|
|
X+Y = T, where T is the total number of rooms (called <code class="display"><span class="extract">size</span></code> below). The
|
|
spread is by definition S = X-Y. Therefore the size of the smaller zone
|
|
is given by Y = (T-S)/2. We use this to ensure that the division is worth
|
|
the time it takes.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MIN_ONECUT_ZONE_SIZE</span><span class="plain"> 2</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">MIN_TWOCUT_ZONE_SIZE</span><span class="plain"> 3</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Look at the results and return connections to cut, if any look good enough</span> <span class="cwebmacronumber">24.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">size</span><span class="plain"> - </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">])/2 >= </span><span class="constant">MIN_ONECUT_ZONE_SIZE</span><span class="plain">) {</span>
|
|
<span class="plain">*</span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">best_from1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">best_to1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">way</span><span class="plain"> = </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">];</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">size</span><span class="plain"> - </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">])/2 >= </span><span class="constant">MIN_TWOCUT_ZONE_SIZE</span><span class="plain">) {</span>
|
|
<span class="plain">*</span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">best_from1</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">best_to1</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">way</span><span class="plain"> = </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">from2</span><span class="plain"> = </span><span class="identifier">best_from2</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">to2</span><span class="plain"> = </span><span class="identifier">best_to2</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">way2</span><span class="plain"> = </span><span class="identifier">best_dir2</span><span class="plain">[</span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">size</span><span class="plain"> - </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">])/2 >= </span><span class="constant">MIN_TWOCUT_ZONE_SIZE</span><span class="plain">) {</span>
|
|
<span class="plain">*</span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">best_from1</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">best_to1</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">way</span><span class="plain"> = </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">from2</span><span class="plain"> = </span><span class="identifier">best_from2</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">to2</span><span class="plain"> = </span><span class="identifier">best_to2</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="plain">*</span><span class="identifier">way2</span><span class="plain"> = </span><span class="identifier">best_dir2</span><span class="plain">[</span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">];</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP24">§24</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§25. </b>The return value of <code class="display"><span class="extract">PL::SpatialMap::assign_generation_count</span></code> is the number of rooms which
|
|
it, and its recursive incarnations, visit in total. But as noted above, it
|
|
also records data in the arrays it is passed pointers to; that's what the
|
|
last eleven arguments are for. Otherwise: <code class="display"><span class="extract">at</span></code> is the room we are currently at,
|
|
and <code class="display"><span class="extract">from</span></code> is the one we've just come from, or <code class="display"><span class="extract">NULL</span></code> if this is the opening
|
|
call; <code class="display"><span class="extract">size</span></code> is the number of rooms in the submap.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::assign_generation_count</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">size</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">best_spread</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">best_from1</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">best_to1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">best_dir1</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">best_from2</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">best_to2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">best_dir2</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">contact_generation</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">contact_from</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">contact_to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">contact_dir</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rooms_visited</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">generation</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">locking_to_neighbours</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Exclude generating this way if we don't need to</span> <span class="cwebmacronumber">25.1</span>><span class="character">;</span>
|
|
<<span class="cwebmacro">Actually generate this way</span> <span class="cwebmacronumber">25.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">locking_to_neighbours</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Exclude generating this way if we don't need to</span> <span class="cwebmacronumber">25.1</span>><span class="character">;</span>
|
|
<<span class="cwebmacro">Actually generate this way</span> <span class="cwebmacronumber">25.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rooms_visited</span><span class="plain"> + 1;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::assign_generation_count is used in <a href="#SP24">§24</a>, <a href="#SP25_2">§25.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_1"></a><b>§25.1. </b>We eliminate: routes from the current room to itself, or back the way
|
|
we just came to get here; routes to rooms with equal or higher generation
|
|
counts than the current one — those are places already visited; and
|
|
routes to rooms with lower generations — but those are contacts, so
|
|
we may need to record them before moving on.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">What this leaves is cases where <code class="display"><span class="extract">T_generation</span></code> is zero, that is, where
|
|
<code class="display"><span class="extract">T</span></code> is a room with no generation count. This ensures <code class="display"><span class="extract">PL::SpatialMap::assign_generation_count</span></code>
|
|
is called at most once on each room.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Exclude generating this way if we don't need to</span> <span class="cwebmacronumber">25.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">at</span><span class="plain">) || (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">from</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">T_generation</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T_generation</span><span class="plain"> >= </span><span class="identifier">generation</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">T_generation</span><span class="plain"> > 0) && (</span><span class="identifier">T_generation</span><span class="plain"> < </span><span class="identifier">generation</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">observed_generation</span><span class="plain"> = </span><span class="identifier">T_generation</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">observed_from</span><span class="plain"> = </span><span class="identifier">at</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">observed_to</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">observed_dir</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Contact hasss been made</span> <span class="cwebmacronumber">25.1.1</span>><span class="plain">;</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25">§25</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2"></a><b>§25.2. </b>At this point, it's as if we have been sent out to explore a labyrinth.
|
|
One problem we have is that we can't see what lies beyond here, with our
|
|
own eyes. "The underground rooms I can speak of only from report, because
|
|
the Egyptians in charge refused to let me see them, as they contain the
|
|
tombs of the kings who built the labyrinth, and also the tombs of the
|
|
sacred crocodiles" (Herodotus). So we must send out explorers who will
|
|
report back, but that costs us resources. "One doctrine called for
|
|
guarding every intersection such as this one. But I had already used two
|
|
men to guard our escape hole; if I left 10 per cent of my force at each
|
|
intersection, mighty soon I would be ten-percented to death" (Heinlein).
|
|
We must be careful of men, too: we can't afford to send out explorers
|
|
indefinitely because the running time and stack consumption would then be
|
|
prohibitive. The traditional approach is to unwind a ball of wool to avoid
|
|
going around in circles, but we'll instead use the generation counts — we
|
|
might imagine writing these on the ground everywhere we go.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">So let us think of ourselves as dividing the party, and sending out a team of
|
|
explorers across the bridge from <code class="display"><span class="extract">at</span></code> to <code class="display"><span class="extract">T</span></code>, telling them to explore every
|
|
possible avenue, and record any contacts they make with the world we
|
|
already know about. We will wait here until they get back, and ask them how
|
|
many new places they managed to visit. Maybe there's a whole world over
|
|
there, maybe just a broom cupboard.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Actually generate this way</span> <span class="cwebmacronumber">25.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inner_contact_generation</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">], </span><span class="identifier">inner_contact_dir</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">inner_contact_from</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">], *</span><span class="identifier">inner_contact_to</span><span class="plain">[</span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">];</span>
|
|
<<span class="cwebmacro">Give the new team of explorers a fresh clipboard</span> <span class="cwebmacronumber">25.2.1</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">generation</span><span class="plain"> + 1;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rooms_explored_in_the_beyond</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::assign_generation_count</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">size</span><span class="plain">,</span>
|
|
<span class="identifier">best_spread</span><span class="plain">,</span>
|
|
<span class="identifier">best_from1</span><span class="plain">, </span><span class="identifier">best_to1</span><span class="plain">, </span><span class="identifier">best_dir1</span><span class="plain">,</span>
|
|
<span class="identifier">best_from2</span><span class="plain">, </span><span class="identifier">best_to2</span><span class="plain">, </span><span class="identifier">best_dir2</span><span class="plain">,</span>
|
|
<span class="identifier">inner_contact_generation</span><span class="plain">, </span><span class="identifier">inner_contact_from</span><span class="plain">, </span><span class="identifier">inner_contact_to</span><span class="plain">, </span><span class="identifier">inner_contact_dir</span><span class="plain">);</span>
|
|
<span class="identifier">rooms_visited</span><span class="plain"> += </span><span class="identifier">rooms_explored_in_the_beyond</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Copy interesting items from the returning team's clipboard to ours</span> <span class="cwebmacronumber">25.2.2</span>><span class="character">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">locking_to_neighbours</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Consider this link as a potential cut-position</span> <span class="cwebmacronumber">25.2.3</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25">§25</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2_1"></a><b>§25.2.1. </b>Each fresh team of explorers gets a fresh clipboard on which to record what
|
|
they see — hence the new set of <code class="display"><span class="extract">inner_contact_*</span></code> arrays. (They don't get
|
|
individual copies of the <code class="display"><span class="extract">best_*</span></code> arrays, though — that's the point of these;
|
|
they're shared in common among all of the explorers.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Give the new team of explorers a fresh clipboard</span> <span class="cwebmacronumber">25.2.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain"> = 0; </span><span class="identifier">j</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="identifier">inner_contact_generation</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = -1;</span>
|
|
<span class="identifier">inner_contact_from</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">inner_contact_to</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">inner_contact_dir</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = -1;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_2">§25.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2_2"></a><b>§25.2.2. </b>When the explorers get back, tired but happy, we look at their clipboard,
|
|
and see if those contacts excite us too — which they may not, because what
|
|
seemed to them a rediscovery might not seem that way to us; they've seen
|
|
more of the world than we have. So we copy their contacts onto our own
|
|
clipboard only if they are contacts to places we know about, too.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Copy interesting items from the returning team's clipboard to ours</span> <span class="cwebmacronumber">25.2.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain"> = 0; </span><span class="identifier">j</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">observed_generation</span><span class="plain"> = </span><span class="identifier">inner_contact_generation</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">observed_generation</span><span class="plain"> > 0) && (</span><span class="identifier">observed_generation</span><span class="plain"> < </span><span class="identifier">generation</span><span class="plain">)) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">observed_from</span><span class="plain"> = </span><span class="identifier">inner_contact_from</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">observed_to</span><span class="plain"> = </span><span class="identifier">inner_contact_to</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">observed_dir</span><span class="plain"> = </span><span class="identifier">inner_contact_dir</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
|
|
<<span class="cwebmacro">Contact hasss been made</span> <span class="cwebmacronumber">25.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_2">§25.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2_3"></a><b>§25.2.3. </b>Our clipboard contains a short list of observed contacts, sorted with
|
|
lowest observed generation first. (If more contacts are observed than will
|
|
fit on the clipboard, they're thrown away.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Consider this link as a potential cut-position</span> <span class="cwebmacronumber">25.2.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_contacts_found</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain"> = 0; </span><span class="identifier">j</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inner_contact_generation</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] > 0)</span>
|
|
<span class="identifier">no_contacts_found</span><span class="plain">++;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_contacts_found</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">spread</span><span class="plain"> = </span><span class="identifier">size</span><span class="plain"> - 2*</span><span class="identifier">rooms_explored_in_the_beyond</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spread</span><span class="plain"> < 0) </span><span class="identifier">spread</span><span class="plain"> = -</span><span class="identifier">spread</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_contacts_found</span><span class="plain"> == 0)</span>
|
|
<<span class="cwebmacro">Cutting on this link would disconnect the submap</span> <span class="cwebmacronumber">25.2.3.1</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_contacts_found</span><span class="plain"> == 1)</span>
|
|
<<span class="cwebmacro">Cutting on this link and the contact found would disconnect the submap</span> <span class="cwebmacronumber">25.2.3.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_2">§25.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2_3_1"></a><b>§25.2.3.1. </b>If exploration outward from here never resulted in a contact with known
|
|
territory, then cutting this link strands the far side as a disconnected zone.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Cutting on this link would disconnect the submap</span> <span class="cwebmacronumber">25.2.3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spread</span><span class="plain"> < </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">]) {</span>
|
|
<span class="identifier">best_spread</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">] = </span><span class="identifier">spread</span><span class="plain">;</span>
|
|
<span class="identifier">best_from1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">] = </span><span class="identifier">at</span><span class="plain">;</span>
|
|
<span class="identifier">best_to1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">] = </span><span class="identifier">T</span><span class="plain">;</span>
|
|
<span class="identifier">best_dir1</span><span class="plain">[</span><span class="constant">BEST_ONECUT_ER</span><span class="plain">] = </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_2_3">§25.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_2_3_2"></a><b>§25.2.3.2. </b>If exploration found just one contact, then that link, plus this one, would
|
|
if both removed cut off the far side. We have to be careful that we never
|
|
cut along locks, only along map connections; we know that the <code class="display"><span class="extract">at</span></code> to <code class="display"><span class="extract">T</span></code>
|
|
link isn't a lock, because we never come here in <code class="display"><span class="extract">locking_to_neighbours</span></code>
|
|
mode. But we don't know that for the observed contact, so we check by hand.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The division is "parallel" if the two links are in the same or opposite
|
|
direction, like the two long tubes of a trombone; this makes it easier to
|
|
slide the zones to and fro without angular distortion, so we prefer it if
|
|
we can get it.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Cutting on this link and the contact found would disconnect the submap</span> <span class="cwebmacronumber">25.2.3.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">inner_contact_from</span><span class="plain">[0], </span><span class="identifier">inner_contact_dir</span><span class="plain">[0]) == </span><span class="identifier">inner_contact_to</span><span class="plain">[0]) </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">r</span><span class="plain"> = </span><span class="constant">BEST_TWOCUT_ER</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">inner_contact_dir</span><span class="plain">[0] == </span><span class="identifier">i</span><span class="plain">) || (</span><span class="identifier">inner_contact_dir</span><span class="plain">[0] == </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">)))</span>
|
|
<span class="identifier">r</span><span class="plain"> = </span><span class="constant">BEST_PARALLEL_TWOCUT_ER</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spread</span><span class="plain"> < </span><span class="identifier">best_spread</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">]) {</span>
|
|
<span class="identifier">best_spread</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">spread</span><span class="plain">;</span>
|
|
<span class="identifier">best_from1</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">at</span><span class="plain">; </span><span class="identifier">best_to1</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">T</span><span class="plain">; </span><span class="identifier">best_dir1</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">best_from2</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">inner_contact_from</span><span class="plain">[0];</span>
|
|
<span class="identifier">best_to2</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">inner_contact_to</span><span class="plain">[0];</span>
|
|
<span class="identifier">best_dir2</span><span class="plain">[</span><span class="identifier">r</span><span class="plain">] = </span><span class="identifier">inner_contact_dir</span><span class="plain">[0];</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_2_3">§25.2.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25_1_1"></a><b>§25.1.1. </b>This is a piece of code used twice in the above routine: it puts the
|
|
contact <code class="display"><span class="extract">observed_from</span></code> to <code class="display"><span class="extract">observed_to</span></code> onto our clipboard, provided that
|
|
there's room and/or it is interesting enough. We use an insertion-sort to
|
|
keep the clipboard in ascending generation order: this would be slow if the
|
|
contact arrays were large, but <code class="display"><span class="extract">CLIPBOARD_SIZE</span></code> is tiny.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Contact hasss been made</span> <span class="cwebmacronumber">25.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> = 0; </span><span class="identifier">k</span><span class="plain"> < </span><span class="constant">CLIPBOARD_SIZE</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">contact_generation</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] == -1) ||</span>
|
|
<span class="plain">(</span><span class="identifier">observed_generation</span><span class="plain"> <= </span><span class="identifier">contact_generation</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">])) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">l</span><span class="plain"> = </span><span class="constant">CLIPBOARD_SIZE</span><span class="plain">-1; </span><span class="identifier">l</span><span class="plain"> > </span><span class="identifier">k</span><span class="plain">; </span><span class="identifier">l</span><span class="plain">--) {</span>
|
|
<span class="identifier">contact_generation</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">] = </span><span class="identifier">contact_generation</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">-1];</span>
|
|
<span class="identifier">contact_from</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">] = </span><span class="identifier">contact_from</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">-1]; </span><span class="identifier">contact_to</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">] = </span><span class="identifier">contact_to</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">-1];</span>
|
|
<span class="identifier">contact_dir</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">] = </span><span class="identifier">contact_dir</span><span class="plain">[</span><span class="identifier">l</span><span class="plain">-1];</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">contact_generation</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] = </span><span class="identifier">observed_generation</span><span class="plain">;</span>
|
|
<span class="identifier">contact_from</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] = </span><span class="identifier">observed_from</span><span class="plain">; </span><span class="identifier">contact_to</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] = </span><span class="identifier">observed_to</span><span class="plain">;</span>
|
|
<span class="identifier">contact_dir</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">] = </span><span class="identifier">observed_dir</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP25_1">§25.1</a>, <a href="#SP25_2_2">§25.2.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§26. Zones 1 and 2 for a single cut. </b>Suppose we have decided to cut the submap between rooms <code class="display"><span class="extract">R1</span></code> and <code class="display"><span class="extract">R2</span></code>, in the
|
|
belief that this will disconnect the submap into two components. If that in
|
|
fact proves to be the case (as it always should) then we set the <code class="display"><span class="extract">zone</span></code> field
|
|
to <code class="display"><span class="extract">Z1</span></code> for all rooms in the R1 component, and <code class="display"><span class="extract">Z2</span></code> on the R1 side. We set
|
|
<code class="display"><span class="extract">Z1_count</span></code> and <code class="display"><span class="extract">Z2_count</span></code> to the sizes of these components, and return <code class="display"><span class="extract">TRUE</span></code>.
|
|
If, however, cutting does not disconnect the submap, then some mistake has
|
|
been made; we return <code class="display"><span class="extract">FALSE</span></code> and the rest is undefined.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It is essential for <code class="display"><span class="extract">Z1</span></code> and <code class="display"><span class="extract">Z2</span></code> to be different. What we will do is to
|
|
spread out these zone values from <code class="display"><span class="extract">R1</span></code> and <code class="display"><span class="extract">R2</span></code> along all spatial
|
|
relationships not being cut; if this results in R2 being hit by the flood
|
|
from R1, or vice versa, then we're in the <code class="display"><span class="extract">FALSE</span></code> case.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::divide_into_zones_onecut</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R1</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">Z1_count</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">Z2_count</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z2</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R1</span><span class="plain"> == </span><span class="identifier">R2</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't divide"</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z1</span><span class="plain">; </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z2</span><span class="plain">;</span>
|
|
<span class="plain">*</span><span class="identifier">Z1_count</span><span class="plain"> = 0; *</span><span class="identifier">Z2_count</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">contacts</span><span class="plain"> = 0;</span>
|
|
<span class="plain">*</span><span class="identifier">Z1_count</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::divide_into_zones_onecut_r</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">, &</span><span class="identifier">contacts</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">contacts</span><span class="plain"> > 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">*</span><span class="identifier">Z2_count</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::divide_into_zones_onecut_r</span><span class="plain">(</span><span class="identifier">R2</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">, &</span><span class="identifier">contacts</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 0)</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z1</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R1</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z1</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == </span><span class="identifier">Z2</span><span class="plain">) &&</span>
|
|
<span class="plain">((*</span><span class="identifier">Z1_count</span><span class="plain">) > 1) && ((*</span><span class="identifier">Z2_count</span><span class="plain">) > 1)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::divide_into_zones_onecut is used in <a href="#SP23_1_2">§23.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27"></a><b>§27. </b>And this is the recursive flooding routine — essentially it's a much
|
|
simplified version of the exploration code above. <code class="display"><span class="extract">from</span></code> is the room we're
|
|
currently at; <code class="display"><span class="extract">zone_capital</span></code> is the one we started from, within our zone;
|
|
<code class="display"><span class="extract">foreign_capital</span></code> is corresponding room of the other zone, so (a) we
|
|
mustn't travel on the direct route between the capitals — that's the line
|
|
which has been cut — and (b) we abandon the moment we find our zone
|
|
impinging on the foreign zone, because that means there's no way to divide
|
|
our original component into two disjoint connected zones.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::divide_into_zones_onecut_r</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">our_capital</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">foreign_capital</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">borders</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rooms_visited</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">our_zone</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) </span><<span class="cwebmacro">Consider whether to spread the zone to room T</span> <span class="cwebmacronumber">27.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) </span><<span class="cwebmacro">Consider whether to spread the zone to room T</span> <span class="cwebmacronumber">27.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">rooms_visited</span><span class="plain"> + 1;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::divide_into_zones_onecut_r is used in <a href="#SP26">§26</a>, <a href="#SP27_1">§27.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27_1"></a><b>§27.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Consider whether to spread the zone to room T</span> <span class="cwebmacronumber">27.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">T_zone</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">, </span><span class="identifier">foreign_zone</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">foreign_capital</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T_zone</span><span class="plain"> == </span><span class="identifier">our_zone</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">our_capital</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">foreign_capital</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">foreign_capital</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">our_capital</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T_zone</span><span class="plain"> == </span><span class="identifier">foreign_zone</span><span class="plain">) { (*</span><span class="identifier">borders</span><span class="plain">)++; </span><span class="reserved">continue</span><span class="plain">; }</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">our_zone</span><span class="plain">;</span>
|
|
<span class="identifier">rooms_visited</span><span class="plain"> +=</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_onecut_r</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">our_capital</span><span class="plain">, </span><span class="identifier">foreign_capital</span><span class="plain">, </span><span class="identifier">borders</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP27">§27</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28"></a><b>§28. Zones 1 and 2 for a double cut. </b>This is more or less the same, but simpler, since it can't determine whether
|
|
we've chosen the cuts correctly, so doesn't even try.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::divide_into_zones_twocut</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">div_T1</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">other_F</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">div_T2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z1</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z2</span><span class="plain">) {</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z1</span><span class="plain">; </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">div_T1</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z2</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_twocut_r</span><span class="plain">(</span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">div_T1</span><span class="plain">, </span><span class="identifier">other_F</span><span class="plain">, </span><span class="identifier">div_T2</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_twocut_r</span><span class="plain">(</span><span class="identifier">div_T1</span><span class="plain">, </span><span class="identifier">div_F1</span><span class="plain">, </span><span class="identifier">div_T1</span><span class="plain">, </span><span class="identifier">other_F</span><span class="plain">, </span><span class="identifier">div_T2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::divide_into_zones_twocut is used in <a href="#SP23_1_2">§23.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP29"></a><b>§29. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::divide_into_zones_twocut_r</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">not_X1</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">not_Y1</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">not_X2</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">not_Y2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">Z</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) </span><<span class="cwebmacro">Consider once again whether to spread the zone to room T</span> <span class="cwebmacronumber">29.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) </span><<span class="cwebmacro">Consider once again whether to spread the zone to room T</span> <span class="cwebmacronumber">29.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::divide_into_zones_twocut_r is used in <a href="#SP28">§28</a>, <a href="#SP29_1">§29.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP29_1"></a><b>§29.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Consider once again whether to spread the zone to room T</span> <span class="cwebmacronumber">29.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">T</span><span class="plain"> != </span><span class="identifier">at</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 0)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">not_X1</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">not_Y1</span><span class="plain">)) || ((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">not_Y1</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">not_X1</span><span class="plain">)))</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">not_X2</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">not_Y2</span><span class="plain">)) || ((</span><span class="identifier">at</span><span class="plain"> == </span><span class="identifier">not_Y2</span><span class="plain">) && (</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">not_X2</span><span class="plain">)))</span>
|
|
<span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = </span><span class="identifier">Z</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::divide_into_zones_twocut_r</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">not_X1</span><span class="plain">, </span><span class="identifier">not_Y1</span><span class="plain">, </span><span class="identifier">not_X2</span><span class="plain">, </span><span class="identifier">not_Y2</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP29">§29</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30"></a><b>§30. Tactics. </b>At long last we can forget about dividing submaps, and concentrate on the
|
|
four tactics for improving the layout of a given submap. We're going to do
|
|
all kinds of heuristic things here, some of them with iffy running times,
|
|
which is one reason why the above divide-and-conquer tricks were wise
|
|
(the other that divisions also reduce the complexity of the pieces we
|
|
need to work on).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We'll often experimentally change something, see what that does, then
|
|
change our minds. For really large-scale experimental changes to the grid
|
|
it's convenient to have a sort of global undo. Note that lock positions
|
|
after restoration must be consistent, since they were consistent at save
|
|
time.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::save_component_positions</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>saved_gridpos</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::restore_component_positions</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>saved_gridpos</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::save_component_positions is used in <a href="#SP23_1_4">§23.1.4</a>, <a href="#SP31">§31</a>, <a href="#SP35_1">§35.1</a>, <a href="#SP37_1_1">§37.1.1</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::restore_component_positions is used in <a href="#SP23_1_4">§23.1.4</a>, <a href="#SP31">§31</a>, <a href="#SP35_1">§35.1</a>, <a href="#SP37_1_1">§37.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP31"></a><b>§31. The cooling tactic. </b>The whole universe was in a hot dense state: as we begin each component,
|
|
every room is at (0,0,0) unless locking causes it to offset slightly, so that
|
|
almost every exit is very hot indeed. We now enter the era of cooling,
|
|
when a great expansion occurs.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This is an iterative process, and if we ran this algorithm indefinitely it
|
|
would very likely lock up, continually moving rooms back and forth but never
|
|
solving its underlying geometric problems. So cooling may only continue so
|
|
long as component heat is strictly reduced on each round.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Cooling has the great virtue that each round runs in O(S) time, where S
|
|
is the number of rooms in the submap. It's quite hard to estimate the
|
|
total running time, but in practice the number of rounds seldom exceeds
|
|
3 or 4, even on quite bad maps, and because cooling is essentially a
|
|
local process there's no reason to expect the number of rounds to grow much
|
|
if S grows. So my guess is that cooling is O(S) in practice.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Another virtue is that cooling alone works in many easy cases. If there are
|
|
no locks, and no multiple exits between pairs of rooms A to B, then cooling
|
|
is guaranteed to find a perfect (heat 0) grid positioning if one exists.
|
|
There are plenty of Inform projects for which that happens: "Bronze",
|
|
for instance, has a single component of 55 rooms, and one round of cooling
|
|
reduces this to absolute zero.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cool_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">TACTIC: Cooling submap %d: initial heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat_before_round</span><span class="plain"> = </span><span class="identifier">initial_heat</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rounds</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cooling round %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, ++</span><span class="identifier">rounds</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>cooled</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::save_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="functiontext">PL::SpatialMap::cool_component_from</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> == 0) </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> >= </span><span class="identifier">heat_before_round</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::restore_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cooling round %d raised heat, so undone.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Cooling round %d leaves penalty %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">heat_before_round</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">,</span>
|
|
<span class="string">"Cooling submap %d done (%d round(s)): cooled by %d at cost of %d drognas\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">,</span>
|
|
<span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="identifier">cooling_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::cool_submap is used in <a href="#SP23">§23</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32"></a><b>§32. </b>Cooling is done room by room within the component, but we get slightly
|
|
better results if it is allowed to spread through the component along exits
|
|
as they cool than if it is simply performed on the rooms in creation order.
|
|
Since the map likely contains circular routes, rooms are flagged so that they
|
|
can only be cooled once in a given round.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cool_component_from</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>cooled</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>cooled</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">];</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">MAX_DIRECTIONS</span><span class="plain">];</span>
|
|
<<span class="cwebmacro">Find the exits from this room and their current heats</span> <span class="cwebmacronumber">32.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Iteratively cool as many exits as possible</span> <span class="cwebmacronumber">32.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::cool_component_from is used in <a href="#SP31">§31</a>, <a href="#SP32_2">§32.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_1"></a><b>§32.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Find the exits from this room and their current heats</span> <span class="cwebmacronumber">32.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">PL::SpatialMap::find_exit_heat</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32_2"></a><b>§32.2. </b>An important point here is that we don't re-measure the heat of the exits
|
|
after cooling. If we did, we might find that cooling is having no effect, and
|
|
then lock up. We're simply trying to deal with the heat as it looked at the
|
|
start of the process; this means there are at most 12 iterations.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The reason we do this in what looks an indirect way (why iterate at all?) is
|
|
to cope better with cases where there are two different exits from R to S.
|
|
This frequently happens in IF maps:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>The Exalted Throne is above the Ziggurat. [...] South from the Throne is the Ziggurat.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">Now there are two exits from Z to E: up and north. They cannot simultaneously
|
|
be cooled. The rule we follow is that we never cool an exit if another exit
|
|
between the two rooms is already cold — this keeps us from endless flipping
|
|
our choice (up from Z to E on cooling round 1, then north on round 2, then up
|
|
on round 3, and so on).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">However, it makes a big difference to the style of the map we produce which
|
|
choice we make. Because the code below tries the exits in direction number
|
|
order, and because lateral directions (N, NE, E, SE, S, SW, W, NW) have
|
|
lower direction numbers than vertical (U, D), the effect is to prefer lateral
|
|
choices over vertical ones. This is a good choice for two reasons: (i) given
|
|
the way we're going to plot the map on a web page, vertical offsets are
|
|
harder to judge by eye; and (ii) IF authors often use "both N and U"-style
|
|
connections to convey that the landscape isn't totally flat, but they're
|
|
still talking about a two-dimensional surface. (Cartographers have always
|
|
done this. The French map IGN 3535 OT, N\'evache-Mont Thabor, shows the
|
|
Rois Mages mountains as if you could walk southeast from Modane and take in
|
|
all three in an afternoon stroll.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Iteratively cool as many exits as possible</span> <span class="cwebmacronumber">32.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">TRUE</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">exits_cooled</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</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">exit_heats</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] > 0) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] == 0) && (</span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">])) {</span>
|
|
<span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 0; </span><span class="identifier">exits_cooled</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] > 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::cool_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = 0; </span><span class="identifier">exits_cooled</span><span class="plain">++;</span>
|
|
<span class="functiontext">PL::SpatialMap::cool_component_from</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] > 0) && (</span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] == </span><span class="identifier">exit_rooms</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">])) {</span>
|
|
<span class="identifier">exit_heats</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">] = 0; </span><span class="identifier">exits_cooled</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">exits_cooled</span><span class="plain"> == 0) </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33"></a><b>§33. </b>To cool an exit is to move the destination room into the perfect grid
|
|
position so that the exit's heat is 0. Note that we must always maintain
|
|
locking, and that we provide a convenient "undo" mechanism in case the
|
|
result made matters worse. (Cooling one exit may simply make other exits
|
|
hotter, since the destination room falls out of alignment with its other
|
|
neighbours.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">saved_to</span><span class="plain">; </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Saved_position</span><span class="plain">;</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::undo_cool_exit</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::move_room_to</span><span class="plain">(</span><span class="identifier">saved_to</span><span class="plain">, </span><span class="identifier">Saved_position</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Undoing move of $O\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">saved_to</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cool_exit</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">exit</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">exit</span><span class="plain">);</span>
|
|
<span class="identifier">saved_to</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">Saved_position</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">length</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">exit</span><span class="plain">];</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="functiontext">Geometry::vec_scale</span><span class="plain">(</span><span class="identifier">length</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">));</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Geometry::vec_eq</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">), </span><span class="identifier">N</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
|
|
<span class="functiontext">PL::SpatialMap::move_room_to</span><span class="plain">(</span><span class="identifier">saved_to</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Moving $O %s from $O: now at (%d,%d,%d)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">to</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_icon_label</span><span class="plain">(</span><span class="identifier">exit</span><span class="plain">), </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">N</span><span class="element">.x</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::undo_cool_exit is used in <a href="#SP34_1">§34.1</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::cool_exit is used in <a href="#SP32_2">§32.2</a>, <a href="#SP34_1">§34.1</a>, <a href="#SP35_1">§35.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34"></a><b>§34. The quenching tactic. </b>After the age of cooling, we can expect the universe to be mostly cold, but
|
|
with local hot-spots where the geometry is distorted because the map is
|
|
simply awkward nearby. Because this tends to be a local problem, we try to
|
|
find a local solution — it's actually just individualised exit cooling.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This theoretically runs in O(S^3) time: note that the measurement of
|
|
submap heat is itself O(S), and we perform this inside a loop of O(S),
|
|
which in turn happens within a repetition which might run for every link
|
|
in the map, also O(S). In practice, there are never many quenching rounds,
|
|
so it's really "only" O(S^2). Still, this is why we don't want to quench
|
|
on large connected submaps.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::quench_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">avoid1</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">avoid2</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">TACTIC: Quenching submap %d: initial heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> + 1, </span><span class="identifier">rounds</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain"> < </span><span class="identifier">last_heat</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Quenching round %d begins with heat at %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, ++</span><span class="identifier">rounds</span><span class="plain">, </span><span class="identifier">heat</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">successes</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</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="functiontext">PL::SpatialMap::find_exit_heat</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) > 0)</span>
|
|
<<span class="cwebmacro">Attempt to quench this heated link</span> <span class="cwebmacronumber">34.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Quenching round %d had %d success(es).\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">, </span><span class="identifier">successes</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Quenching submap %d done: cooled by %d at cost of %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="identifier">quenching_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::quench_submap is used in <a href="#SP23_1_1">§23.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34_1"></a><b>§34.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Attempt to quench this heated link</span> <span class="cwebmacronumber">34.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</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">T</span><span class="plain"> == </span><span class="identifier">avoid1</span><span class="plain">) && (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">avoid2</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">T</span><span class="plain"> == </span><span class="identifier">avoid2</span><span class="plain">) && (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">avoid1</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Quenching $O %s to $O.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_icon_label</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::cool_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">h</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain"> >= </span><span class="identifier">heat</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::undo_cool_exit</span><span class="plain">();</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Undoing: would have resulted in heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Accepting: reduces heat to %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="identifier">successes</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP34">§34</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP35"></a><b>§35. The diffusion tactic. </b>Where quenching fails to help much, this is usually because rooms are packed
|
|
too tightly together, and need to be eased apart. This makes space for
|
|
more interesting configurations and makes it easier to get rid of the very
|
|
large collision heats, though the heat of some individual links actually
|
|
rises, since there's a penalty for increasing length.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We call this process diffusion, since the heat eddies away into the local
|
|
neighbourhood as the rooms shimmy apart.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::diffuse_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">TACTIC: Diffusing submap %d: initial heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> + 1, </span><span class="identifier">rounds</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain"> < </span><span class="identifier">last_heat</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Diffusion round %d with heat at %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, ++</span><span class="identifier">rounds</span><span class="plain">, </span><span class="identifier">heat</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</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">T</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Try diffusion along this link</span> <span class="cwebmacronumber">35.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Diffusing submap %d done after %d round(s): "</span>
|
|
<span class="string">"cooled by %d at cost of %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">,</span>
|
|
<span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="identifier">diffusion_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::diffuse_submap is used in <a href="#SP23_1_1">§23.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP35_1"></a><b>§35.1. </b>Essentially we try lengthening the link by 1 unit, and see if that makes
|
|
things better; however, it tends to be useless just moving one room, because
|
|
that's very likely only moving a collision heat (let's say) one place down
|
|
the grid. So we move not only the room but also a whole clump of nearby
|
|
rooms whose exits are cold (or which are locked to each other).
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Try diffusion along this link</span> <span class="cwebmacronumber">35.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</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">L</span><span class="plain"> > -1) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Lengthening $O %s to $O to %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_icon_label</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">+1);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::save_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">O</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">L</span><span class="plain">+1;</span>
|
|
<span class="functiontext">PL::SpatialMap::cool_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">O</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 1;</span>
|
|
<span class="functiontext">PL::SpatialMap::diffuse_across</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 2) && (</span><span class="identifier">S</span><span class="plain"> != </span><span class="identifier">R</span><span class="plain">))</span>
|
|
<span class="functiontext">PL::SpatialMap::translate_room</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> >= </span><span class="identifier">heat</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::restore_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exit_lengths</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Lengthening left heat undecreased at %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Lengthening reduced heat to %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">;</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP35">§35</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP36"></a><b>§36. </b>This recursively expands zone 2 to include rooms connected by cold links,
|
|
except that it's forbidden to including <code class="display"><span class="extract">avoiding</span></code> (the room we are trying
|
|
to lengthen away from).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::diffuse_across</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">avoiding</span><span class="plain">) {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 2;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 1)) </span><span class="functiontext">PL::SpatialMap::diffuse_across</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">avoiding</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 1) && (</span><span class="identifier">T</span><span class="plain"> != </span><span class="identifier">avoiding</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::find_exit_heat</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == 0))</span>
|
|
<span class="functiontext">PL::SpatialMap::diffuse_across</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">avoiding</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::diffuse_across is used in <a href="#SP35_1">§35.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37"></a><b>§37. The radiation tactic. </b>Here, we look for misaligned links, because they'll look broken to the eye,
|
|
and see if it's possible to slide a block of rooms in one of the compass
|
|
directions so that the link becomes aligned again.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This is such a neat trick, and so (relatively!) fast, that we apply it in
|
|
two circumstances: not only when tidying up after diffusion, but also after
|
|
we have rejoined a divided submap. (It's especially good for that because
|
|
after a two-point cut we often have a situation where one of the cut links
|
|
is put back tidily but the other is dislocated.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It's hard to prove that radiation is rapid, because it certainly wouldn't be
|
|
if used earlier on. What saves us is that by now there are few misaligned
|
|
links.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::radiate_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">TACTIC: Radiating submap %d: initial heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> + 1, </span><span class="identifier">rounds</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain"> < </span><span class="identifier">last_heat</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Radiation round %d with heat at %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, ++</span><span class="identifier">rounds</span><span class="plain">, </span><span class="identifier">heat</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="identifier">last_heat</span><span class="plain"> = </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">R</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">T</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::exit_aligned</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Attempt to radiate from this misaligned link</span> <span class="cwebmacronumber">37.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Radiating submap %d done after %d round(s): "</span>
|
|
<span class="string">"cooled by %d at cost of %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">rounds</span><span class="plain">,</span>
|
|
<span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="identifier">radiation_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::radiate_submap is used in <a href="#SP23_1">§23.1</a>, <a href="#SP23_1_1">§23.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37_1"></a><b>§37.1. </b>We try some 40 possible translations of the R end of the link, hoping to
|
|
find that one or more of them will align with the T end. T will stay
|
|
fixed: note that by symmetry, if this doesn't work, we'll end up testing
|
|
the same link with the roles of R and T reversed later. Typically, there
|
|
are only three or four viable new positions for R.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_RADIATION_DISTANCE</span><span class="plain"> 5</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Attempt to radiate from this misaligned link</span> <span class="cwebmacronumber">37.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Map misaligned on $O %s to $O.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">R</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_icon_label</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">);</span>
|
|
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">O</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">E</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::direction_as_vector</span><span class="plain">(</span><span class="identifier">j</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> = 1; </span><span class="identifier">L</span><span class="plain"> <= </span><span class="constant">MAX_RADIATION_DISTANCE</span><span class="plain">; </span><span class="identifier">L</span><span class="plain">++) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_scale</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">E</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">O</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::exit_aligned</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Radiation is geometrically possible here</span> <span class="cwebmacronumber">37.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::set_room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">O</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">Escape</span><span class="plain">: ;</span>
|
|
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP37">§37</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP37_1_1"></a><b>§37.1.1. </b>At this point setting this up is much the same as for diffusion:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Radiation is geometrically possible here</span> <span class="cwebmacronumber">37.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Aligned at offset %d, %d, %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">D</span><span class="element">.x</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::save_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 1;</span>
|
|
<span class="functiontext">PL::SpatialMap::radiate_across</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 2) && (</span><span class="identifier">S</span><span class="plain"> != </span><span class="identifier">R</span><span class="plain">)) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">, </span><span class="string">"Comoving $O\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::translate_room</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain"> >= </span><span class="identifier">heat</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::restore_component_positions</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">,</span>
|
|
<span class="string">"Radiating left heat undecreased at %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP_WORKINGS</span><span class="plain">,</span>
|
|
<span class="string">"Radiating reduced heat to %d.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="identifier">heat</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">;</span>
|
|
<span class="reserved">goto</span><span class="plain"> </span><span class="identifier">Escape</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP37_1">§37.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_30"></a><b>§8.30. </b>This is the clever part of radiation, and the reason why we only allow R
|
|
to radiate outward on cardinal points of the compass. Once again we will
|
|
move a whole clump of R's neighbours along with it, preserving their positions
|
|
relative to each other; but this time we define the boundary of the clump
|
|
by links in the radiation direction, or its opposite. The result is that
|
|
no exit can ever become misaligned during radiation; the only movements
|
|
happen parallel to the only links whose endpoints move with respect to each
|
|
other. (With just one exception, of course: the link between R and T,
|
|
where by construction the movement will make a previously unaligned link
|
|
become aligned.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It follows that radiation can never increase the number of unaligned links.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::radiate_across</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">avoiding</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">not_this_way</span><span class="plain">) {</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 2;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">not_this_way_either</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">not_this_way</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_slock</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 1))</span>
|
|
<span class="functiontext">PL::SpatialMap::radiate_across</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">avoiding</span><span class="plain">, </span><span class="identifier">not_this_way</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOOP_OVER_LATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap</span><span class="plain">(</span><span class="identifier">at</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">T</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 1) && (</span><span class="identifier">T</span><span class="plain"> != </span><span class="identifier">avoiding</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">i</span><span class="plain"> != </span><span class="identifier">not_this_way</span><span class="plain">) && (</span><span class="identifier">i</span><span class="plain"> != </span><span class="identifier">not_this_way_either</span><span class="plain">))</span>
|
|
<span class="functiontext">PL::SpatialMap::radiate_across</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">avoiding</span><span class="plain">, </span><span class="identifier">not_this_way</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::radiate_across is used in <a href="#SP37_1_1">§37.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_31"></a><b>§8.31. The explosion tactic. </b>Sometimes, in the direst emergency, there's one tried and tested way to
|
|
get rid of a lot of concentrated heat: to explode. Specifically, we get
|
|
rid of collisions between rooms (which we absolutely forbid) by moving them
|
|
apart until there are no further collisions. We do this even if it should
|
|
increase the heat measure, though in practice the penalty for room collisions
|
|
is so high that this is unlikely to be an issue.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain"> 3</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::explode_submap</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">), </span><span class="identifier">initial_spending</span><span class="plain"> = </span><span class="identifier">drognas_spent</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"\</span><span class="plain">n</span><span class="string">TACTIC: Exploding submap %d: initial heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">keep_trying</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">moves</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">keep_trying</span><span class="plain">) {</span>
|
|
<span class="identifier">keep_trying</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">At</span><span class="plain"> = </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::occupied_in_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">At</span><span class="plain">) >= 2) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Collision: pushing $O away\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">x</span><span class="plain">, </span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">coldest</span><span class="plain"> = </span><span class="constant">FUSION_POINT</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Coldest</span><span class="plain"> = </span><span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain"> + 1, 0, 0);</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> = -</span><span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain">; </span><span class="identifier">x</span><span class="plain"><=</span><span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain">; </span><span class="identifier">x</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">y</span><span class="plain"> = -</span><span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain">; </span><span class="identifier">y</span><span class="plain"><=</span><span class="constant">MAX_EXPLOSION_DISTANCE</span><span class="plain">; </span><span class="identifier">y</span><span class="plain">++)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">x</span><span class="plain"> != 0) || (</span><span class="identifier">y</span><span class="plain"> != 0)) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">V</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">At</span><span class="plain">, </span><span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x</span><span class="plain">, </span><span class="identifier">y</span><span class="plain">, 0));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::occupied_in_submap</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">) == 0) {</span>
|
|
<span class="functiontext">PL::SpatialMap::move_room_to</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">V</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">h</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain"> < </span><span class="identifier">coldest</span><span class="plain">) { </span><span class="identifier">Coldest</span><span class="plain"> = </span><span class="identifier">V</span><span class="plain">; </span><span class="identifier">coldest</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::move_room_to</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">At</span><span class="plain">, </span><span class="identifier">Coldest</span><span class="plain">));</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Moving $O to blank offset (%d,%d,%d) for heat %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">R</span><span class="plain">, </span><span class="identifier">Coldest</span><span class="element">.x</span><span class="plain">, </span><span class="identifier">Coldest</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">Coldest</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">, </span><span class="identifier">coldest</span><span class="plain">);</span>
|
|
<span class="identifier">keep_trying</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">moves</span><span class="plain">++;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::find_submap_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Exploding submap %d done after %d move(s): "</span>
|
|
<span class="string">"cooled by %d at cost of %d drognas\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">moves</span><span class="plain">,</span>
|
|
<span class="identifier">initial_heat</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>heat</span><span class="plain">, </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">);</span>
|
|
<span class="identifier">explosion_spending</span><span class="plain"> += </span><span class="identifier">drognas_spent</span><span class="plain"> - </span><span class="identifier">initial_spending</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::explode_submap is used in <a href="#SP23_1_1">§23.1.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32"></a><b>§8.32. Stage 3, positioning the components. </b>Having cooled and diffused each component, we now treat them as rigid
|
|
bodies, but still have to establish their spatial relationship to each
|
|
other. We ensure that the components do not overlap by the crude method of
|
|
making their bounding cuboids disjoint, even though this will often mean
|
|
that there is wasted space on the page. (Thus we do not, for instance, use
|
|
the trick adopted by the British Ordnance Survey in mapping the outlying
|
|
island of St Kilda on an inset square of what would otherwise be empty
|
|
ocean on OS18 "Sound of Harris", despite its being separated by about
|
|
60km from the position shown.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(4) Position the components in space</span> <span class="cwebmacronumber">8.32</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ncom</span><span class="plain"> = </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain">);</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> **</span><span class="identifier">sorted</span><span class="plain"> =</span>
|
|
<span class="identifier">Memory::I7_calloc</span><span class="plain">(</span><span class="identifier">ncom</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *), </span><span class="identifier">INDEX_SORTING_MREASON</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Sort the components into decreasing order of size</span> <span class="cwebmacronumber">8.32.2</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, *</span><span class="identifier">previous_mc</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Drill_square_O</span><span class="plain"> = </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Drill_square_At</span><span class="plain"> = </span><span class="identifier">Zero_vector</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">drill_square_side</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">cuboid</span><span class="plain"> </span><span class="identifier">box</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">ncom</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
|
|
<span class="identifier">sub</span><span class="plain"> = </span><span class="identifier">sorted</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">sub</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Position this map component in space</span> <span class="cwebmacronumber">8.32.1</span>><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">=</span><span class="identifier">ncom</span><span class="plain">-1; </span><span class="identifier">j</span><span class="plain">>=0; </span><span class="identifier">j</span><span class="plain">--) {</span>
|
|
<span class="identifier">sub</span><span class="plain"> = </span><span class="identifier">sorted</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">];</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">PL::SpatialMap::no_links_to_placed_components</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) == 1)) {</span>
|
|
<<span class="cwebmacro">Position this map component in space</span> <span class="cwebmacronumber">8.32.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">Memory::I7_array_free</span><span class="plain">(</span><span class="identifier">sorted</span><span class="plain">, </span><span class="identifier">INDEX_SORTING_MREASON</span><span class="plain">, </span><span class="identifier">ncom</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_1"></a><b>§8.32.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Position this map component in space</span> <span class="cwebmacronumber">8.32.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">previous_mc</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">x_max</span><span class="plain"> = </span><span class="identifier">box</span><span class="element">.corner1.x</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0.x</span><span class="plain"> + 1;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain"> == 1) && (</span><span class="functiontext">PL::SpatialMap::component_is_isolated</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">)))</span>
|
|
<<span class="cwebmacro">Use the drill-square strategy to place this component</span> <span class="cwebmacronumber">8.32.1.2</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::component_is_adjoining</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">))</span>
|
|
<<span class="cwebmacro">Use the optimised inset strategy to place this component</span> <span class="cwebmacronumber">8.32.1.3</span>>
|
|
<span class="reserved">else</span>
|
|
<<span class="cwebmacro">Use the side-by-side strategy to place this component</span> <span class="cwebmacronumber">8.32.1.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Geometry::merge_cuboid</span><span class="plain">(&</span><span class="identifier">box</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds</span><span class="plain">);</span>
|
|
<span class="identifier">previous_mc</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32">§8.32</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_1_1"></a><b>§8.32.1.1. </b>Here we simply place the component immediately to the right of its
|
|
predecessor, with the same baseline, and on the level of the benchmark room.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Use the side-by-side strategy to place this component</span> <span class="cwebmacronumber">8.32.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Component %d (size %d): side by side strategy\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain">);</span>
|
|
<span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">,</span>
|
|
<span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x_max</span><span class="plain">, </span><span class="identifier">box</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">,</span>
|
|
<span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">benchmark_room</span><span class="plain">).</span><span class="identifier">z</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32_1">§8.32.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_1_2"></a><b>§8.32.1.2. </b>The drill square is a way to place large numbers of single-room components,
|
|
such as exist in IF works where rooms are being plaited together live during
|
|
play and have no initial map. Side-by-side placement would be horrible for
|
|
such rooms. We will form the most nearly square rectangle which can hold
|
|
them, arranged so that it's slightly wider than it is tall. In effect, this
|
|
rectangle — the "drill square" — is then placed side-by-side as if it's
|
|
one big component.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Use the drill-square strategy to place this component</span> <span class="cwebmacronumber">8.32.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Component %d (size %d): drill square strategy\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">drill_square_side</span><span class="plain"> == 0) {</span>
|
|
<span class="identifier">Drill_square_O</span><span class="plain"> =</span>
|
|
<span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">box</span><span class="element">.corner1.x</span><span class="plain"> + 1, </span><span class="identifier">box</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">benchmark_room</span><span class="plain">).</span><span class="identifier">z</span><span class="plain">);</span>
|
|
<span class="identifier">Drill_square_At</span><span class="plain"> = </span><span class="identifier">Drill_square_O</span><span class="plain">;</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sing</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sing</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sing</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain"> == 1) && (</span><span class="functiontext">PL::SpatialMap::component_is_isolated</span><span class="plain">(</span><span class="identifier">sing</span><span class="plain">)))</span>
|
|
<span class="identifier">N</span><span class="plain">++;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">drill_square_side</span><span class="plain">*</span><span class="identifier">drill_square_side</span><span class="plain"> < </span><span class="identifier">N</span><span class="plain">) </span><span class="identifier">drill_square_side</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">drill_square_side</span><span class="plain">*</span><span class="identifier">drill_square_side</span><span class="plain"> > </span><span class="identifier">N</span><span class="plain">) </span><span class="identifier">drill_square_side</span><span class="plain">--;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Drill square: side %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">drill_square_side</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Drill_square_At</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">));</span>
|
|
<span class="identifier">Drill_square_At</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Drill_square_At</span><span class="plain">, </span><span class="functiontext">Geometry::vec</span><span class="plain">(0, 1, 0));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Drill_square_At</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> - </span><span class="identifier">Drill_square_O</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> == </span><span class="identifier">drill_square_side</span><span class="plain">)</span>
|
|
<span class="identifier">Drill_square_At</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span><span class="identifier">Drill_square_At</span><span class="plain">,</span>
|
|
<span class="functiontext">Geometry::vec</span><span class="plain">(1, -</span><span class="identifier">drill_square_side</span><span class="plain">, 0));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32_1">§8.32.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_1_3"></a><b>§8.32.1.3. </b>Insetting is used if our new component has a map connection in the IN or
|
|
OUT directions with an already-placed component; if we can, we want to place
|
|
the new component into the map as close as possible to the room it connects
|
|
with.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">MAX_OFFSET</span><span class="plain"> 1</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Use the optimised inset strategy to place this component</span> <span class="cwebmacronumber">8.32.1.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"Component %d (size %d): optimised inset strategy\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">outer</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">inner</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="functiontext">PL::SpatialMap::find_link_to_placed_components</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, &</span><span class="identifier">outer</span><span class="plain">, &</span><span class="identifier">inner</span><span class="plain">);</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Best_offset</span><span class="plain"> =</span>
|
|
<span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">x_max</span><span class="plain">, </span><span class="identifier">box</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">,</span>
|
|
<span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">benchmark_room</span><span class="plain">).</span><span class="identifier">z</span><span class="plain"> - </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">outer</span><span class="plain">) && (</span><span class="identifier">inner</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">dx</span><span class="plain"> = 0, </span><span class="identifier">dy</span><span class="plain"> = 0, </span><span class="identifier">dz</span><span class="plain"> = 0, </span><span class="identifier">min_s</span><span class="plain"> = </span><span class="constant">FUSION_POINT</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">dx</span><span class="plain"> = -</span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dx</span><span class="plain"> <= </span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dx</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">dy</span><span class="plain"> = -</span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dy</span><span class="plain"> <= </span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dy</span><span class="plain">++)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">dz</span><span class="plain"> = -</span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dz</span><span class="plain"> <= </span><span class="constant">MAX_OFFSET</span><span class="plain">; </span><span class="identifier">dz</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">dx</span><span class="plain"> == 0) && (</span><span class="identifier">dy</span><span class="plain"> == 0) && (</span><span class="identifier">dz</span><span class="plain"> == 0)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">Offset</span><span class="plain"> =</span>
|
|
<span class="functiontext">Geometry::vec_plus</span><span class="plain">(</span>
|
|
<span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">outer</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">inner</span><span class="plain">)),</span>
|
|
<span class="functiontext">Geometry::vec</span><span class="plain">(</span><span class="identifier">dx</span><span class="plain">, </span><span class="identifier">dy</span><span class="plain">, </span><span class="identifier">dz</span><span class="plain">));</span>
|
|
<<span class="cwebmacro">Try this possible offset component position</span> <span class="cwebmacronumber">8.32.1.3.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">Best_offset</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32_1">§8.32.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_1_3_1"></a><b>§8.32.1.3.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Try this possible offset component position</span> <span class="cwebmacronumber">8.32.1.3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">Offset</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">s</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_component_placement_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">s</span><span class="plain"> < </span><span class="identifier">min_s</span><span class="plain">) {</span>
|
|
<span class="identifier">min_s</span><span class="plain"> = </span><span class="identifier">s</span><span class="plain">; </span><span class="identifier">Best_offset</span><span class="plain"> = </span><span class="identifier">Offset</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">PL::SpatialMap::move_component</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="functiontext">Geometry::vec_negate</span><span class="plain">(</span><span class="identifier">Offset</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32_1_3">§8.32.1.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_32_2"></a><b>§8.32.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Sort the components into decreasing order of size</span> <span class="cwebmacronumber">8.32.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">) </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">) </span><span class="identifier">sorted</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">++] = </span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="identifier">qsort</span><span class="plain">(</span><span class="identifier">sorted</span><span class="plain">, (</span><span class="identifier">size_t</span><span class="plain">) </span><span class="identifier">ncom</span><span class="plain">, </span><span class="reserved">sizeof</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *), </span><span class="functiontext">PL::SpatialMap::compare_components</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8_32">§8.32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP38"></a><b>§38. </b>The following means the components are sorted in descending size order,
|
|
but in order of creation within each size; when we get down to the
|
|
singletons, we sort by order of creation of the single rooms they
|
|
contain.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::compare_components</span><span class="plain">(</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent1</span><span class="plain">, </span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">ent2</span><span class="plain">) {</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">mc1</span><span class="plain"> = *((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">connected_submap</span><span class="plain"> **) </span><span class="identifier">ent1</span><span class="plain">);</span>
|
|
<span class="reserved">const</span><span class="plain"> </span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">mc2</span><span class="plain"> = *((</span><span class="reserved">const</span><span class="plain"> </span><span class="reserved">connected_submap</span><span class="plain"> **) </span><span class="identifier">ent2</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="identifier">mc2</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain"> - </span><span class="identifier">mc1</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">mc1</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain"> == 1) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R1</span><span class="plain"> = </span><span class="identifier">mc1</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain"> = </span><span class="identifier">mc2</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R1</span><span class="plain">) && (</span><span class="identifier">R2</span><span class="plain">)) { </span> <span class="comment">which should always happen, but just in case of an error</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">reg1</span><span class="plain"> = </span><span class="functiontext">PL::Regions::enclosing</span><span class="plain">(</span><span class="identifier">R1</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">reg2</span><span class="plain"> = </span><span class="functiontext">PL::Regions::enclosing</span><span class="plain">(</span><span class="identifier">R2</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">reg1</span><span class="plain">) && (</span><span class="identifier">reg2</span><span class="plain"> == </span><span class="identifier">NULL</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">reg1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) && (</span><span class="identifier">reg2</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">reg1</span><span class="plain">) {</span>
|
|
<span class="identifier">d</span><span class="plain"> = </span><span class="identifier">reg1</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain"> - </span><span class="identifier">reg2</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">d</span><span class="plain"> = </span><span class="identifier">R1</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain"> - </span><span class="identifier">R2</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> != 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">mc1</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain"> - </span><span class="identifier">mc2</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::compare_components is used in <a href="#SP8_32_2">§8.32.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP39"></a><b>§39. </b>We should define what we mean by "adjoining" and "isolated". The first
|
|
means it has a link (which must be IN or OUT) to an already-positioned
|
|
component; the second means it has no link at all to any other component.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::component_is_adjoining</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::no_links_to_placed_components</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) > 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::component_is_isolated</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::no_links_to_other_components</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">) == 0) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::component_is_adjoining is used in <a href="#SP8_32_1">§8.32.1</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::component_is_isolated is used in <a href="#SP8_32_1">§8.32.1</a>, <a href="#SP8_32_1_2">§8.32.1.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP40"></a><b>§40. </b>In theory this has O(R^2) running time, but it's very unlikely that there
|
|
are R components of size 1, so in practice it's much better than that.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_component_placement_heat</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">other</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">other</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">other</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::occupied_in_submap</span><span class="plain">(</span><span class="identifier">other</span><span class="plain">, </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)))</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FUSION_POINT</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::find_cross_component_heat</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain"> >= </span><span class="constant">FUSION_POINT</span><span class="plain">) </span><span class="identifier">heat</span><span class="plain"> = </span><span class="constant">FUSION_POINT</span><span class="plain"> - 1;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_component_placement_heat is used in <a href="#SP8_32_1_3_1">§8.32.1.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP41"></a><b>§41. </b>Where:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_cross_component_heat</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain"> = 0;</span>
|
|
<span class="functiontext">PL::SpatialMap::cross_component_links</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, &</span><span class="identifier">heat</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">heat</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_link_to_placed_components</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">,</span>
|
|
<span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">outer</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">inner</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::cross_component_links</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">outer</span><span class="plain">, </span><span class="identifier">inner</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::no_links_to_placed_components</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cross_component_links</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::no_links_to_other_components</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cross_component_links</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_cross_component_heat is used in <a href="#SP40">§40</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_link_to_placed_components is used in <a href="#SP8_32_1_3">§8.32.1.3</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::no_links_to_placed_components is used in <a href="#SP8_32">§8.32</a>, <a href="#SP39">§39</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::no_links_to_other_components is used in <a href="#SP39">§39</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP42"></a><b>§42. </b>So, now we have to define our Swiss-army-knife routine to cope with all
|
|
these requirements. We not only count non-lattice connections to other
|
|
components (IN and OUT links, basically), but also score how bad they are,
|
|
if requested, and record the first we find, if requested.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">There can't be any lattice connections to other components, because two
|
|
rooms connected that way are by definition in the same component.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::cross_component_links</span><span class="plain">(</span><span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">outer</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> **</span><span class="identifier">inner</span><span class="plain">,</span>
|
|
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">heat</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">posnd</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_links</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain">) *</span><span class="identifier">heat</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_NONLATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">d</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap_cross</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R2</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> != </span><span class="identifier">sub</span><span class="plain">)) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">posnd</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) || (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain">)) {</span>
|
|
<span class="identifier">no_links</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inner</span><span class="plain">) *</span><span class="identifier">inner</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outer</span><span class="plain">) *</span><span class="identifier">outer</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain">) *</span><span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(*</span><span class="identifier">heat</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_cross_link_heat</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">sub</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">posnd</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_NONLATTICE_DIRECTIONS</span><span class="plain">(</span><span class="identifier">d</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R2</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::read_smap_cross</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R2</span><span class="plain">) && (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain"> == </span><span class="identifier">sub</span><span class="plain">)) {</span>
|
|
<span class="identifier">no_links</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outer</span><span class="plain">) *</span><span class="identifier">outer</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inner</span><span class="plain">) *</span><span class="identifier">inner</span><span class="plain"> = </span><span class="identifier">R2</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain">) *</span><span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(*</span><span class="identifier">heat</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_cross_link_heat</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">R2</span><span class="plain">, </span><span class="identifier">d</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_links</span><span class="plain"> == 0) </span><<span class="cwebmacro">Look for van der Waals forces</span> <span class="cwebmacronumber">42.1</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">no_links</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::cross_component_links is used in <a href="#SP41">§41</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP42_1"></a><b>§42.1. </b>When there are no map connections or locks, there may still be a very weak
|
|
bond between rooms simply because they belong to the same region. We only
|
|
look at these weak bonds for singleton regions, for simplicity and to keep
|
|
running time in check.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Look for van der Waals forces</span> <span class="cwebmacronumber">42.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain"> == 1) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>first_room_in_submap</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain">) { </span> <span class="comment">which should always happen, but just in case of an error</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">reg</span><span class="plain"> = </span><span class="functiontext">PL::Regions::enclosing</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">reg</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, *</span><span class="identifier">closest_S</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">closest</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain"> != </span><span class="identifier">R</span><span class="plain">) && (</span><span class="functiontext">PL::Regions::enclosing</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">) == </span><span class="identifier">reg</span><span class="plain">))</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">posnd</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) || (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">)-</span><span class="element">>submap</span><span class="plain">-</span><span class="element">>positioned</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">diff</span><span class="plain"> = 2*(</span><span class="identifier">R</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain"> - </span><span class="identifier">S</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">diff</span><span class="plain"> < 0) </span><span class="identifier">diff</span><span class="plain"> = 1-</span><span class="identifier">diff</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">closest_S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">diff</span><span class="plain"> < </span><span class="identifier">closest</span><span class="plain">)) {</span>
|
|
<span class="identifier">closest</span><span class="plain"> = </span><span class="identifier">diff</span><span class="plain">; </span><span class="identifier">closest_S</span><span class="plain"> = </span><span class="identifier">S</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">closest_S</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">SPATIAL_MAP</span><span class="plain">, </span><span class="string">"vdW force between $O and $O\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">closest_S</span><span class="plain">);</span>
|
|
<span class="identifier">no_links</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">outer</span><span class="plain">) *</span><span class="identifier">outer</span><span class="plain"> = </span><span class="identifier">closest_S</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inner</span><span class="plain">) *</span><span class="identifier">inner</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heat</span><span class="plain">) *</span><span class="identifier">heat</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::heat_sum</span><span class="plain">(*</span><span class="identifier">heat</span><span class="plain">, </span><span class="functiontext">PL::SpatialMap::find_cross_link_heat</span><span class="plain">(</span><span class="identifier">closest_S</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">, 3));</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP42">§42</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_33"></a><b>§8.33. </b>"How bad they are" uses another heat-like measure. This one gives an
|
|
enormous penalty for being wrong vertically; people just don't like
|
|
reading maps where an inside room is displayed on the floor above or below.
|
|
It also gives preference to the green jagged arrow directions when placing
|
|
insets — this makes the map line up elegantly.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::find_cross_link_heat</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">S</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"bad room distance"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::component_metric</span><span class="plain">(</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">), </span><span class="identifier">dir</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::component_metric</span><span class="plain">(</span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P1</span><span class="plain">, </span><span class="reserved">vector</span><span class="plain"> </span><span class="identifier">P2</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">dir</span><span class="plain">) {</span>
|
|
<span class="reserved">vector</span><span class="plain"> </span><span class="identifier">D</span><span class="plain"> = </span><span class="functiontext">Geometry::vec_minus</span><span class="plain">(</span><span class="identifier">P1</span><span class="plain">, </span><span class="identifier">P2</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">b</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">dir</span><span class="plain"> == 10) || (</span><span class="identifier">dir</span><span class="plain"> == 11)) { </span> <span class="comment">IN and OUT respectively</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="element">.x</span><span class="plain"> > 0) </span><span class="identifier">b</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="element">.x</span><span class="plain"> < 0) </span><span class="identifier">b</span><span class="plain">--;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> > 0) </span><span class="identifier">b</span><span class="plain">--;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> < 0) </span><span class="identifier">b</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dir</span><span class="plain"> == 11) </span><span class="identifier">b</span><span class="plain"> = -</span><span class="identifier">b</span><span class="plain">;</span>
|
|
<span class="identifier">b</span><span class="plain"> += 2;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">dir</span><span class="plain"> == 3) { </span> <span class="comment">SOUTH, the notional direction for van der Waals forces</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> > 0) </span><span class="identifier">b</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> < 0) </span><span class="identifier">b</span><span class="plain">--;</span>
|
|
<span class="identifier">b</span><span class="plain"> += 2;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> 2*</span><span class="identifier">b</span><span class="plain"> + </span><span class="identifier">D</span><span class="element">.x</span><span class="plain">*</span><span class="identifier">D</span><span class="element">.x</span><span class="plain"> + </span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">*</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">y</span><span class="plain"> + 100*</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">*</span><span class="identifier">D</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::find_cross_link_heat is used in <a href="#SP42">§42</a>, <a href="#SP42_1">§42.1</a>.</p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::component_metric appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_34"></a><b>§8.34. Stage 5, bounding the universe. </b>Short and sweet. We make <code class="display"><span class="extract">Universe</span></code> the minimal-sized cuboid containing each room.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(5) Find the universal bounding cuboid</span> <span class="cwebmacronumber">8.34</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Universe</span><span class="plain"> = </span><span class="functiontext">Geometry::empty_cuboid</span><span class="plain">();</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="functiontext">Geometry::adjust_cuboid</span><span class="plain">(&</span><span class="identifier">Universe</span><span class="plain">, </span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8_35"></a><b>§8.35. Stage 6, removing blank planes. </b>We need to avoid what might be an infinite loop in awkward cases where
|
|
locking means that blank planes are inevitable.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">(6) Remove any blank lateral planes</span> <span class="cwebmacronumber">8.35</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">safety_count</span><span class="plain"> = </span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="identifier">instance</span><span class="plain">);</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">safety_count</span><span class="plain">-- >= 0) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">blank_z</span><span class="plain"> = 0, </span><span class="identifier">blank_plane_found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">z</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">z</span><span class="plain"> = </span><span class="identifier">Universe</span><span class="element">.corner1</span><span class="plain">.</span><span class="identifier">z</span><span class="plain"> - 1; </span><span class="identifier">z</span><span class="plain"> >= </span><span class="identifier">Universe</span><span class="element">.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain"> + 1; </span><span class="identifier">z</span><span class="plain">--) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">occupied</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">).</span><span class="identifier">z</span><span class="plain"> == </span><span class="identifier">z</span><span class="plain">) </span><span class="identifier">occupied</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">occupied</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<span class="identifier">blank_z</span><span class="plain"> = </span><span class="identifier">z</span><span class="plain">;</span>
|
|
<span class="identifier">blank_plane_found</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">blank_plane_found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">).</span><span class="identifier">z</span><span class="plain"> > </span><span class="identifier">blank_z</span><span class="plain">)</span>
|
|
<span class="functiontext">PL::SpatialMap::translate_room</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">D_vector</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP43"></a><b>§43. Precis. </b>It turns out to be useful to test the above algorithm on maps of actual IF
|
|
works. But they tend to have large source texts full of irrelevancies to
|
|
the spatial layout, so in order to extract the arrangement cleanly, we
|
|
can make use of the following:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::log_precis_of_map</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"[Precis of source text giving map layout follows.]\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">) </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_object</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">Declare the regions and doors in the precis</span> <span class="cwebmacronumber">43.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Declare the rooms in the precis, starting with the start room</span> <span class="cwebmacronumber">43.2</span>><span class="plain">;</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0;</span>
|
|
<span class="plain">}</span>
|
|
<<span class="cwebmacro">Declare the map connections in the precis</span> <span class="cwebmacronumber">43.3</span>><span class="plain">;</span>
|
|
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="functiontext">PL::SpatialMap::visit_to_transcribe</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">[Precis complete.]\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::log_precis_of_map is used in <a href="#SP8">§8</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP43_1"></a><b>§43.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Declare the regions and doors in the precis</span> <span class="cwebmacronumber">43.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_direction</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain"> >= 12)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">OW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="functiontext">PL::Map::get_value_of_opposite_property</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is a direction. The opposite of %+W is %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">OW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_region</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is a region.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_door</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is a door.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">World::Inferences::get_prop_state</span><span class="plain">(</span>
|
|
<span class="identifier">Instances::as_subject</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">), </span><span class="identifier">P_other_side</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">Rvalues::to_object_instance</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">X</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">XW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The other side of %+W is %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">XW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP43">§43</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP43_2"></a><b>§43.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Declare the rooms in the precis, starting with the start room</span> <span class="cwebmacronumber">43.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Instances::of_kind</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">K_room</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is a room.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">reg</span><span class="plain"> = </span><span class="functiontext">PL::Regions::enclosing</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">reg</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RGW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">reg</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">reg</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> == 1) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is a region.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">RGW</span><span class="plain">);</span>
|
|
<span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">reg</span><span class="plain">)-></span><span class="identifier">zone</span><span class="plain"> = 0;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is in %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">, </span><span class="identifier">RGW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">start</span><span class="plain"> = </span><span class="functiontext">PL::Player::get_start_room</span><span class="plain">();</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">start</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The player is in %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP43">§43</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP43_3"></a><b>§43.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Declare the map connections in the precis</span> <span class="cwebmacronumber">43.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_ROOMS</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_STORY_DIRECTIONS</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">D</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, &</span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) || (</span><span class="identifier">D</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">OW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">) </span><span class="identifier">OW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">D</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">OW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> < 12) {</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">n</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">opp</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::opposite</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is %s of %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">OW</span><span class="plain">, </span><span class="identifier">n</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) && (</span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">opp</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">))</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%s of %+W is nowhere.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="functiontext">PL::SpatialMap::usual_Inform_direction_name</span><span class="plain">(</span><span class="identifier">opp</span><span class="plain">), </span><span class="identifier">OW</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">dir</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">K_direction</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">dir</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain"> == </span><span class="identifier">i</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">DW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W is %W of %+W.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">OW</span><span class="plain">, </span><span class="identifier">DW</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">opp</span><span class="plain"> = </span><span class="functiontext">PL::Map::get_value_of_opposite_property</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">od</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">opp</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) && (</span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">od</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">OPW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%W of %+W is nowhere.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">OPW</span><span class="plain">, </span><span class="identifier">OW</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>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP43">§43</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP44"></a><b>§44. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::visit_to_transcribe</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">SENTENCE_NT</span><span class="plain">) && (</span><span class="identifier">p</span><span class="plain">-></span><span class="identifier">down</span><span class="plain">)) {</span>
|
|
<span class="identifier">Assertions::Traverse::try_special_meaning</span><span class="plain">(</span><span class="identifier">TRAVERSE_FOR_MAP_INDEX_SMFT</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-></span><span class="identifier">down</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::visit_to_transcribe is used in <a href="#SP43">§43</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP45"></a><b>§45. </b>Rather similar code is used for details on the World index.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::index_room_connections</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">RW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">); </span> <span class="comment">name of the origin room</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">dir</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">K_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">dir</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">opp</span><span class="plain"> = </span><span class="functiontext">PL::Map::get_value_of_opposite_property</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">od</span><span class="plain"> = </span><span class="identifier">opp</span><span class="plain">?(</span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">opp</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">):(-1);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">D</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">S</span><span class="plain"> = </span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, &</span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) || (</span><span class="identifier">D</span><span class="plain">)) {</span>
|
|
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 1, </span><span class="string">"tight"</span><span class="plain">);</span>
|
|
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">icon</span><span class="plain"> = </span><span class="string">"e_arrow"</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) && (</span><span class="identifier">D</span><span class="plain">)) </span><span class="identifier">icon</span><span class="plain"> = </span><span class="string">"e_arrow_door"</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">D</span><span class="plain">) </span><span class="identifier">icon</span><span class="plain"> = </span><span class="string">"e_arrow_door_blocked"</span><span class="plain">;</span>
|
|
<span class="identifier">HTML_TAG_WITH</span><span class="plain">(</span><span class="string">"img"</span><span class="plain">, </span><span class="string">"border=0 src=inform:/map_icons/%s.png"</span><span class="plain">, </span><span class="identifier">icon</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;"</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">dir</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" to "</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">D</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" via "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">D</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (a door)"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain">) {</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">B</span><span class="plain"> = </span><span class="identifier">opp</span><span class="plain">?(</span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">od</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">B</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (but "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">opp</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" from "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" is nowhere)"</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">B</span><span class="plain"> != </span><span class="identifier">R</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (but "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">opp</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" from "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">S</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" is "</span><span class="plain">);</span>
|
|
<span class="identifier">Instances::index_name</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">B</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">)-</span><span class="element">>exits_set_at</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">at</span><span class="plain">) </span><span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">)));</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_INSTANCES</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">K_direction</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">PF_I</span><span class="plain">(</span><span class="identifier">map</span><span class="plain">, </span><span class="identifier">dir</span><span class="plain">)-</span><span class="element">>direction_index</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::SpatialMap::room_exit</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">DW</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">dir</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">); </span> <span class="comment">name of the direction</span>
|
|
<span class="identifier">k</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> == 1) {</span>
|
|
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 1, </span><span class="string">"hanging"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<i>add:</i> "</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"; "</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">DW</span><span class="plain">));</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]; </span><span class="identifier">j</span><span class="plain">++) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">j</span><span class="plain">==0) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="identifier">Characters::toupper</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]));</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">j</span><span class="plain">]);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">DW</span><span class="plain">) > 1)</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">" %+W"</span><span class="plain">, </span><span class="identifier">Wordings::trim_first_word</span><span class="plain">(</span><span class="identifier">DW</span><span class="plain">));</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">" from "</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">RW</span><span class="plain">)) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">RW</span><span class="plain">);</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">"here"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">" is .[=0x000A=]"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::Javascript::paste_stream</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">TEMP</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&nbsp;%+W"</span><span class="plain">, </span><span class="identifier">DW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain">>0) </span><span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::index_room_connections is used in 3/tm (<a href="3-tm.html#SP39">§39</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP46"></a><b>§46. Unit testing. </b>The internal test case "map" produces a list of spatial coordinates for
|
|
rooms:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::SpatialMap::log_spatial_layout</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="functiontext">PL::SpatialMap::establish_benchmark_room</span><span class="plain">();</span>
|
|
<span class="functiontext">PL::EPSMap::traverse_for_map_parameters</span><span class="plain">(1);</span>
|
|
<span class="functiontext">PL::SpatialMap::establish_spatial_coordinates</span><span class="plain">();</span>
|
|
<span class="reserved">connected_submap</span><span class="plain"> *</span><span class="identifier">sub</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sub</span><span class="plain">, </span><span class="reserved">connected_submap</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">Map component %d: "</span>
|
|
<span class="string">"extent (%d...%d, %d...%d, %d...%d): population %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0.x</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner1.x</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner1</span><span class="plain">.</span><span class="identifier">y</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner0</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.corner1</span><span class="plain">.</span><span class="identifier">z</span><span class="plain">,</span>
|
|
<span class="identifier">sub</span><span class="plain">-</span><span class="element">>bounds.population</span><span class="plain">);</span>
|
|
<span class="identifier">instance</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_SUBMAP</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">sub</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Instances::get_name</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">R</span><span class="plain"> == </span><span class="identifier">benchmark_room</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Benchmark: "</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%W: %d, %d, %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">,</span>
|
|
<span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">)</span><span class="element">.x</span><span class="plain">,</span>
|
|
<span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">).</span><span class="identifier">y</span><span class="plain">,</span>
|
|
<span class="identifier">Room_position</span><span class="plain">(</span><span class="identifier">R</span><span class="plain">).</span><span class="identifier">z</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function PL::SpatialMap::log_spatial_layout appears nowhere else.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="3-sg.html">Back to 'Spatial Geometry'</a></li><li><a href="3-hm.html">Continue with 'HTML Map'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|