1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/docs/core-module/16-in.html
2020-04-07 01:06:09 +01:00

1196 lines
169 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>16/pp</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 tools</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 '16/in' 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">core</a></li><li><a href="index.html#16">Chapter 16: Inference and Model</a></li><li><b>Inferences</b></li></ul><p class="purpose">To manage the individual pieces of information gathered, with varying degrees of certainty, from assertion sentences. This is mostly information about which objects have what properties.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP7">&#167;7. Creation</a></li><li><a href="#SP9">&#167;9. Drawing inferences</a></li><li><a href="#SP11">&#167;11. Reading inference data</a></li><li><a href="#SP13">&#167;13. Looping over inferences</a></li><li><a href="#SP14">&#167;14. Finding property states</a></li><li><a href="#SP15">&#167;15. Indexing properties of a subject</a></li><li><a href="#SP17">&#167;17. Indexing properties of a specific subject</a></li><li><a href="#SP18">&#167;18. Comparing inferences</a></li><li><a href="#SP20">&#167;20. Joining an inference to what is known about an object</a></li><li><a href="#SP21">&#167;21. Logging inferences</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Inform reads a natural language description of a world. As it runs through, it
collects together the assertions made in this description (such as "On the
table is a hat"), which are sometimes vague (where is this table?), sometimes
imply further facts (the hat cannot be a room, and the table must be a
supporter) and are sometimes contradictory (if, for instance, "The hat is in
the hatbox" has also been read).
</p>
<p class="inwebparagraph">As we have seen, such sentences are reduced to logical propositions, then
asserted true, which results in a sequence of "inferences" being "drawn".
In this section, we see how inferences are stored and what drawing them
entails.
</p>
<p class="inwebparagraph">Each inference represents a single fact, associated with the "inference
subject" it concerns. For instance, if property P of object X has the value V,
that makes an inference about X; but if the fact is that two objects, X and Y,
are related, then that will often be an inference about the relation rather than
about X or Y.
</p>
<p class="inwebparagraph">As this last example shows, up to two other inference subjects can be connected
by the fact in question, besides the INFS to which it is attached.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>There are only two main types of inference, though plugins can and do define
further types.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">ARBITRARY_RELATION_INF</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> </span><span class="comment">fact about an "arbitrary" relation</span>
<span class="definitionkeyword">define</span> <span class="constant">PROPERTY_INF</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment">fact about a property</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>Not all information is positive, or certain. The likelihood of something
being true is measured on the five-point <code class="display"><span class="extract">*_CE</span></code> scale, though an inference
is never allowed to have <code class="display"><span class="extract">UNKNOWN_CE</span></code> status &mdash; that would tell us nothing.
</p>
<p class="inwebparagraph">If C is a certainty level, then we call its absolute value the "absolute
certainty". Thus there are only three absolute certainty levels: unknown,
likely and certain.
</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>When a given sentence is being parsed, there is a prevailing mood of certainty
or uncertainty about the information implied by it, and this is stored in the
following global variable:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">prevailing_mood</span><span class="plain"> = </span><span class="identifier">UNKNOWN_CE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>This is the data structure used to store a single inference. Within the
stock of facts known about a given INFS, the individual inferences are
organised as linked lists; hence the <code class="display"><span class="extract">next</span></code> field.
</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">inference</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inference_type</span><span class="plain">; </span><span class="comment">see above</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">certainty</span><span class="plain">; </span><span class="comment">see above</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inferred_from</span><span class="plain">; </span><span class="comment">from what sentence was this drawn?</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">added_in_construction</span><span class="plain">; </span><span class="comment">or was this drawn during the model completion stage?</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inference_timestamp</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs_ref1</span><span class="plain">; </span><span class="comment">from 0 to 2 other INFSs are connected by this inference</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs_ref2</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec_ref1</span><span class="plain">; </span><span class="comment">used by dynamic relations between non-subjects</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec_ref2</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">inferred_property</span><span class="plain">; </span><span class="comment">property referred to, if any</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inferred_property_value</span><span class="plain">; </span><span class="comment">and its value, if any</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">; </span><span class="comment">next in list of inferences on same subject</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">inference</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure inference is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ns, 7/oaf, 7/rs, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/ass, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Creation. </b>The following routine coins a newly minted inference which is not yet attached
to any subject: but it will not stay unattached for long. Note that if nothing
has been said about likelihood, the sentence is assumed to be factually certain.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inference_timer</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="functiontext">World::Inferences::create_inference</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">type</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">certitude</span><span class="plain">) {</span>
<span class="constant">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">certitude</span><span class="plain"> == </span><span class="identifier">UNKNOWN_CE</span><span class="plain">) </span><span class="identifier">certitude</span><span class="plain"> = </span><span class="identifier">CERTAIN_CE</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">new_i</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain">);</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">inference_timestamp</span><span class="plain"> = </span><span class="identifier">inference_timer</span><span class="plain">++;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> = </span><span class="identifier">type</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain"> = </span><span class="identifier">certitude</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">added_in_construction</span><span class="plain"> = </span><span class="functiontext">Task::is_during_stage</span><span class="plain">(</span><span class="constant">MODEL_COMPLETE_CSEQ</span><span class="plain">);</span>
<span class="identifier">new_i</span><span class="plain">-&gt;</span><span class="element">next</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">new_i</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::create_inference is used in <a href="#SP8">&#167;8</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>Here are our two core inference types:
</p>
<pre class="display">
<span class="reserved">inference</span><span class="plain"> *</span><span class="functiontext">World::Inferences::create_property_inference</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain">) {</span>
<span class="constant">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_inference</span><span class="plain">(</span><span class="constant">PROPERTY_INF</span><span class="plain">, </span><span class="identifier">prevailing_mood</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prevailing_mood</span><span class="plain"> == </span><span class="identifier">UNKNOWN_CE</span><span class="plain">)</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_default_certainty</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain"> = </span><span class="identifier">prn</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain"> = </span><span class="identifier">val</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prn</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">"null property inference"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="functiontext">World::Inferences::create_relation_inference</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs0</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs1</span><span class="plain">) {</span>
<span class="constant">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_inference</span><span class="plain">(</span><span class="constant">ARBITRARY_RELATION_INF</span><span class="plain">, </span><span class="identifier">prevailing_mood</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain"> = </span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs0</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain"> = </span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs1</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="functiontext">World::Inferences::create_relation_inference_spec</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec0</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec1</span><span class="plain">) {</span>
<span class="constant">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_inference</span><span class="plain">(</span><span class="constant">ARBITRARY_RELATION_INF</span><span class="plain">, </span><span class="identifier">prevailing_mood</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain"> = </span><span class="identifier">spec0</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain"> = </span><span class="identifier">spec1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec0</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">spec1</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">"malformed specified relation"</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>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::create_property_inference is used in <a href="#SP9">&#167;9</a>.</p>
<p class="endnote">The function World::Inferences::create_relation_inference is used in <a href="#SP9">&#167;9</a>.</p>
<p class="endnote">The function World::Inferences::create_relation_inference_spec is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Drawing inferences. </b>This is how the rest of Inform records fresh information about the world
model. To "draw" an inference is to create it as a structure and then
"join" it to the list of facts already known about its subject. (This
might not actually accept it; it might be redundant, or contradictory.)
</p>
<p class="inwebparagraph">The two core inferences:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::draw_property</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_property_inference</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
<span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::draw_negated_property</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_property_inference</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">val</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain"> = -</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain">;</span>
<span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::draw_relation</span><span class="plain">(</span><span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain">,</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs0</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs1</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_relation_inference</span><span class="plain">(</span><span class="identifier">infs0</span><span class="plain">, </span><span class="identifier">infs1</span><span class="plain">);</span>
<span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="functiontext">BinaryPredicates::as_subject</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::draw_relation_spec</span><span class="plain">(</span><span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec0</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec1</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_relation_inference_spec</span><span class="plain">(</span><span class="identifier">spec0</span><span class="plain">, </span><span class="identifier">spec1</span><span class="plain">);</span>
<span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="functiontext">BinaryPredicates::as_subject</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::draw_property is used in 5/ins (<a href="5-ins.html#SP36">&#167;36</a>), 6/er (<a href="6-er.html#SP4">&#167;4</a>), 12/ter (<a href="12-ter.html#SP7">&#167;7</a>), 15/ep (<a href="15-ep.html#SP16">&#167;16</a>), 15/ma (<a href="15-ma.html#SP12">&#167;12</a>), 15/spr2 (<a href="15-spr2.html#SP10">&#167;10</a>).</p>
<p class="endnote">The function World::Inferences::draw_negated_property is used in 15/ep (<a href="15-ep.html#SP16">&#167;16</a>).</p>
<p class="endnote">The function World::Inferences::draw_relation is used in 6/er (<a href="6-er.html#SP3">&#167;3</a>).</p>
<p class="endnote">The function World::Inferences::draw_relation_spec is used in 6/er (<a href="6-er.html#SP3">&#167;3</a>).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>And an all-purpose routine provided for plugins to draw customised
inferences of their own:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::draw</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">type</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">about</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">certitude</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs0</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs1</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">World::Inferences::create_inference</span><span class="plain">(</span><span class="identifier">type</span><span class="plain">, </span><span class="identifier">certitude</span><span class="plain">);</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain"> = </span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs0</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain"> = </span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs1</span><span class="plain">);</span>
<span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">about</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::draw appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Reading inference data. </b>Once drawn, inferences are read-only, and the following access routines
allow them to be read.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_timestamp</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">inference_timestamp</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_inference_type</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">inference_type</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">inferred_from</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">certainty</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::set_certainty</span><span class="plain">(</span><span class="reserved">inference</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">ce</span><span class="plain">) {</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain"> = </span><span class="identifier">ce</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::added_in_construction</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">added_in_construction</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">inferred_property</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="reserved">inference</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">-&gt;</span><span class="identifier">inferred_property_value</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">World::Inferences::set_property_value_kind</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">ParseTree::set_kind_of_value</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="identifier">inferred_property_value</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::get_timestamp appears nowhere else.</p>
<p class="endnote">The function World::Inferences::get_inference_type is used in 15/pr (<a href="15-pr.html#SP26">&#167;26</a>).</p>
<p class="endnote">The function World::Inferences::where_inferred is used in <a href="#SP14">&#167;14</a>, 2/si (<a href="2-si.html#SP9">&#167;9</a>), 5/nv (<a href="5-nv.html#SP17">&#167;17</a>), 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>), 15/pr (<a href="15-pr.html#SP26">&#167;26</a>), 15/ia (<a href="15-ia.html#SP1_1">&#167;1.1</a>, <a href="15-ia.html#SP2">&#167;2</a>), 15/epv (<a href="15-epv.html#SP1_1_3">&#167;1.1.3</a>), 16/cmw (<a href="16-cmw.html#SP1_2_2_1_1_1">&#167;1.2.2.1.1.1</a>).</p>
<p class="endnote">The function World::Inferences::get_certainty is used in <a href="#SP14">&#167;14</a>, 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>), 9/imp (<a href="9-imp.html#SP6">&#167;6</a>, <a href="9-imp.html#SP6_1">&#167;6.1</a>), 15/pr (<a href="15-pr.html#SP26">&#167;26</a>), 16/cmw (<a href="16-cmw.html#SP1_2_2">&#167;1.2.2</a>, <a href="16-cmw.html#SP1_2_2_1_1">&#167;1.2.2.1.1</a>).</p>
<p class="endnote">The function World::Inferences::set_certainty is used in 16/cmw (<a href="16-cmw.html#SP1_2_2_1_1">&#167;1.2.2.1.1</a>).</p>
<p class="endnote">The function World::Inferences::added_in_construction is used in 16/cmw (<a href="16-cmw.html#SP1_2_2">&#167;1.2.2</a>, <a href="16-cmw.html#SP1_2_2_1">&#167;1.2.2.1</a>).</p>
<p class="endnote">The function World::Inferences::get_property is used in <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, 2/si (<a href="2-si.html#SP9">&#167;9</a>), 5/nv (<a href="5-nv.html#SP17">&#167;17</a>, <a href="5-nv.html#SP21">&#167;21</a>), 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>), 9/imp (<a href="9-imp.html#SP6">&#167;6</a>), 15/pr (<a href="15-pr.html#SP26">&#167;26</a>), 15/ia (<a href="15-ia.html#SP1">&#167;1</a>, <a href="15-ia.html#SP2">&#167;2</a>), 15/epv (<a href="15-epv.html#SP1_1_3">&#167;1.1.3</a>), 16/cmw (<a href="16-cmw.html#SP1_2_1">&#167;1.2.1</a>, <a href="16-cmw.html#SP1_2_2">&#167;1.2.2</a>, <a href="16-cmw.html#SP1_2_2_1">&#167;1.2.2.1</a>).</p>
<p class="endnote">The function World::Inferences::get_property_value is used in <a href="#SP14">&#167;14</a>, <a href="#SP15">&#167;15</a>, 5/nv (<a href="5-nv.html#SP17">&#167;17</a>), 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>), 15/pr (<a href="15-pr.html#SP26">&#167;26</a>), 15/ia (<a href="15-ia.html#SP2">&#167;2</a>), 16/cmw (<a href="16-cmw.html#SP1_2_2_1_1">&#167;1.2.2.1.1</a>).</p>
<p class="endnote">The function World::Inferences::set_property_value_kind is used in 5/nv (<a href="5-nv.html#SP21">&#167;21</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>Core Inform deals only in INFSs, but plugins often use inferences concerned
only with objects (e.g., for the map), so we also provide a convenient abbreviated
way to extract just reference 1 in object form.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_references</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain">,</span>
<span class="reserved">inference_subject</span><span class="plain"> **</span><span class="identifier">infs1</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> **</span><span class="identifier">infs2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs1</span><span class="plain">) *</span><span class="identifier">infs1</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs2</span><span class="plain">) *</span><span class="identifier">infs2</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_references_spec</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">spec1</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">spec2</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">spec1</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain">; *</span><span class="identifier">spec2</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="functiontext">World::Inferences::get_reference_as_object</span><span class="plain">(</span><span class="reserved">inference</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="functiontext">InferenceSubjects::as_object_instance</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::get_references is used in 6/bp (<a href="6-bp.html#SP33">&#167;33</a>), 6/rlt (<a href="6-rlt.html#SP20_5_1">&#167;20.5.1</a>).</p>
<p class="endnote">The function World::Inferences::get_references_spec is used in 6/bp (<a href="6-bp.html#SP33">&#167;33</a>), 6/rlt (<a href="6-rlt.html#SP28">&#167;28</a>).</p>
<p class="endnote">The function World::Inferences::get_reference_as_object appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Looping over inferences. </b>The following macro prototypes show how to loop through all of the inferences
known concerning a given inference subject, and of a given type. "Positive"
knowledge means that the inferences must have a certainty of likely or better.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">type</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">inf</span><span class="plain"> = (</span><span class="identifier">infs</span><span class="plain">)?(</span><span class="functiontext">InferenceSubjects::get_inferences</span><span class="plain">(</span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">))):</span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">inf</span><span class="plain">; </span><span class="identifier">inf</span><span class="plain"> = </span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="identifier">inference_type</span><span class="plain"> == </span><span class="identifier">type</span><span class="plain">) &amp;&amp; (</span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">))</span>
<span class="definitionkeyword">define</span> <span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">type</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">inf</span><span class="plain"> = (</span><span class="identifier">infs</span><span class="plain">)?(</span><span class="functiontext">InferenceSubjects::get_inferences</span><span class="plain">(</span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">))):</span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">inf</span><span class="plain">; </span><span class="identifier">inf</span><span class="plain"> = </span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> == </span><span class="identifier">type</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Finding property states. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_EO_state</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">infs</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">UNKNOWN_CE</span><span class="plain">;</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">k</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prnbar</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">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) </span><span class="identifier">prnbar</span><span class="plain"> = </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> = </span><span class="identifier">infs</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">; </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">)) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">known</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">known</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">known</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> != </span><span class="identifier">UNKNOWN_CE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prnbar</span><span class="plain"> == </span><span class="identifier">known</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> != </span><span class="identifier">UNKNOWN_CE</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> -</span><span class="identifier">c</span><span class="plain">;</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">UNKNOWN_CE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_EO_state_without_inheritance</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">where</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">infs</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">UNKNOWN_CE</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prnbar</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">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) </span><span class="identifier">prnbar</span><span class="plain"> = </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">known</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_certainty</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">known</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">known</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> != </span><span class="identifier">UNKNOWN_CE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">where</span><span class="plain">) *</span><span class="identifier">where</span><span class="plain"> = </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prnbar</span><span class="plain"> == </span><span class="identifier">known</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> != </span><span class="identifier">UNKNOWN_CE</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">where</span><span class="plain">) *</span><span class="identifier">where</span><span class="plain"> = </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> -</span><span class="identifier">c</span><span class="plain">;</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">UNKNOWN_CE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::verify_prop_states</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">PK</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">VK</span><span class="plain"> = </span><span class="functiontext">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Kinds::Compare::compatible</span><span class="plain">(</span><span class="identifier">VK</span><span class="plain">, </span><span class="identifier">PK</span><span class="plain">) != </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Property value given as $u not $u\n"</span><span class="plain">, </span><span class="identifier">VK</span><span class="plain">, </span><span class="identifier">PK</span><span class="plain">);</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">inf</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_property</span><span class="plain">(2, </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(3, </span><span class="identifier">VK</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_kind</span><span class="plain">(4, </span><span class="identifier">PK</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_LateInferenceProblem</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but that tries to set the value of the '%2' "</span>
<span class="string">"property to %3 - which must be wrong because this property "</span>
<span class="string">"has to be %4."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</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="functiontext">World::Inferences::get_prop_state</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">infs</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">NULL</span><span class="plain">;</span>
<span class="reserved">inference_subject</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"> = </span><span class="identifier">infs</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">; </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">)) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">known</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">known</span><span class="plain"> == </span><span class="identifier">prn</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">inf</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>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">World::Inferences::get_prop_state_at</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">where</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">infs</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">NULL</span><span class="plain">;</span>
<span class="reserved">inference_subject</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"> = </span><span class="identifier">infs</span><span class="plain">; </span><span class="identifier">k</span><span class="plain">; </span><span class="identifier">k</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">)) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">known</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">known</span><span class="plain"> == </span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">where</span><span class="plain">) *</span><span class="identifier">where</span><span class="plain"> = </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</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>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">World::Inferences::get_prop_state_without_inheritance</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">,</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> **</span><span class="identifier">where</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">infs</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">NULL</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">POSITIVE_KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">known</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">known</span><span class="plain"> == </span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">where</span><span class="plain">) *</span><span class="identifier">where</span><span class="plain"> = </span><span class="functiontext">World::Inferences::where_inferred</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">inf</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 World::Inferences::get_EO_state is used in <a href="#SP16">&#167;16</a>.</p>
<p class="endnote">The function World::Inferences::get_EO_state_without_inheritance is used in <a href="#SP17">&#167;17</a>.</p>
<p class="endnote">The function World::Inferences::verify_prop_states is used in 16/is (<a href="16-is.html#SP30">&#167;30</a>).</p>
<p class="endnote">The function World::Inferences::get_prop_state is used in 3/nl (<a href="3-nl.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function World::Inferences::get_prop_state_at appears nowhere else.</p>
<p class="endnote">The function World::Inferences::get_prop_state_without_inheritance is used in <a href="#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. Indexing properties of a subject. </b>This is where the detailed description of a given kind &mdash; what properties it
has, and so on &mdash; is generated.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::index</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">brief</span><span class="plain">) {</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">inf</span><span class="plain">;</span>
<span class="identifier">KNOWLEDGE_LOOP</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="constant">PROPERTY_INF</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Inferences::get_property</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">) == </span><span class="identifier">P_specification</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_property_value</span><span class="plain">(</span><span class="identifier">inf</span><span class="plain">);</span>
<span class="identifier">Index::dequote</span><span class="plain">(</span><span class="identifier">OUT</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">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">))));</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="reserved">property</span><span class="plain">) </span><span class="functiontext">Properties::set_indexed_already_flag</span><span class="plain">(</span><span class="identifier">prn</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">c</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">CERTAIN_CE</span><span class="plain">; </span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="identifier">IMPOSSIBLE_CE</span><span class="plain">; </span><span class="identifier">c</span><span class="plain">--) {</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Text only put here to stop gcc -O2 wrongly reporting an error"</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">UNKNOWN_CE</span><span class="plain">) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CERTAIN_CE:</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Always"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIKELY_CE:</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Usually"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNLIKELY_CE:</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Usually not"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPOSSIBLE_CE:</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Never"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INITIALLY_CE:</span><span class="plain"> </span><span class="identifier">cert</span><span class="plain"> = </span><span class="string">"Initially"</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">World::Inferences::index_provided</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">, </span><span class="identifier">cert</span><span class="plain">, </span><span class="identifier">brief</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">World::Inferences::index_provided</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">LIKELY_CE</span><span class="plain">, </span><span class="string">"Can have"</span><span class="plain">, </span><span class="identifier">brief</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::index is used in 5/ipw (<a href="5-ipw.html#SP3_7">&#167;3.7</a>), 13/ki (<a href="13-ki.html#SP1_11">&#167;1.11</a>).</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. </b>The following lists off the properties of the kind, with the given
state of being boolean, and the given certainty levels:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::has_or_can_have</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">has</span><span class="plain"> = </span><span class="functiontext">World::Inferences::get_EO_state</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">has</span><span class="plain"> == </span><span class="identifier">UNKNOWN_CE</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</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="functiontext">Properties::EitherOr::stored_in_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">LIKELY_CE</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">UNLIKELY_CE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">has</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</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">LIKELY_CE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">UNKNOWN_CE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::index_provided</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">bool</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">cert</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">brief</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">f</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="reserved">property</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_shown_in_index</span><span class="plain">(</span><span class="identifier">prn</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">if</span><span class="plain"> (</span><span class="functiontext">Properties::get_indexed_already_flag</span><span class="plain">(</span><span class="identifier">prn</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="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">) != </span><span class="identifier">bool</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">state</span><span class="plain"> = </span><span class="functiontext">World::Inferences::has_or_can_have</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">state</span><span class="plain"> != </span><span class="identifier">c</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">inherited_state</span><span class="plain"> = </span><span class="functiontext">World::Inferences::has_or_can_have</span><span class="plain">(</span>
<span class="functiontext">InferenceSubjects::narrowest_broader_subject</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">), </span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">state</span><span class="plain"> == </span><span class="identifier">inherited_state</span><span class="plain">) &amp;&amp; (</span><span class="identifier">brief</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">f</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;%s&lt;/i&gt; "</span><span class="plain">, </span><span class="identifier">cert</span><span class="plain">); </span><span class="identifier">f</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">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="functiontext">Properties::set_indexed_already_flag</span><span class="plain">(</span><span class="identifier">prn</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="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prnbar</span><span class="plain"> = </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prnbar</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" &lt;i&gt;not&lt;/i&gt; %+W"</span><span class="plain">, </span><span class="identifier">prnbar</span><span class="plain">-&gt;</span><span class="identifier">name</span><span class="plain">);</span>
<span class="functiontext">Properties::set_indexed_already_flag</span><span class="plain">(</span><span class="identifier">prnbar</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">else</span><span class="plain"> {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain"> = </span><span class="functiontext">Properties::Valued::kind</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (&lt;i&gt;"</span><span class="plain">); </span><span class="identifier">Kinds::Textual::write</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">K</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;/i&gt;)"</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">f</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"."</span><span class="plain">);</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::has_or_can_have appears nowhere else.</p>
<p class="endnote">The function World::Inferences::index_provided is used in <a href="#SP15">&#167;15</a>.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. Indexing properties of a specific subject. </b>This only tells about specific property settings for a given instance.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::index_specific</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prn</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="reserved">property</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_shown_in_index</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">World::Permissions::find</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">TRUE</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="identifier">NULL</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">World::Inferences::get_EO_state_without_inheritance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, &amp;</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">prnbar</span><span class="plain"> = </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prnbar</span><span class="plain">) &amp;&amp; (</span><span class="identifier">S</span><span class="plain"> &lt; </span><span class="constant">0</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">S</span><span class="plain"> != </span><span class="identifier">UNKNOWN_CE</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">k</span><span class="plain"> == </span><span class="constant">1</span><span class="plain">) </span><span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="constant">1</span><span class="plain">, </span><span class="string">"hanging"</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="reserved">if</span><span class="plain"> (</span><span class="identifier">S</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"not "</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</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">P</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">k</span><span class="plain"> &gt; </span><span class="constant">0</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="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">, </span><span class="reserved">property</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_shown_in_index</span><span class="plain">(</span><span class="identifier">prn</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">prn</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">World::Permissions::find</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, </span><span class="identifier">TRUE</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="identifier">NULL</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="functiontext">World::Inferences::get_prop_state_without_inheritance</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">, &amp;</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">S</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">)))) {</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="constant">1</span><span class="plain">, </span><span class="string">"hanging"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W: "</span><span class="plain">, </span><span class="identifier">prn</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"000080"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">));</span>
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">P</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">P</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::index_specific is used in 5/ipw (<a href="5-ipw.html#SP3_9">&#167;3.9</a>).</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Comparing inferences. </b>The following routine is a little like <code class="display"><span class="extract">strcmp</span></code>, the standard C routine
for comparing strings, in that it compares two inferences and returns a
value useful for sorting algorithms: 0 if equal, positive if <code class="display"><span class="extract">i1 &lt; i2</span></code>,
negative if <code class="display"><span class="extract">i2 &lt; i1</span></code>. This is a stable trichotomy; in particular,
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">World::Inferences::compare_inferences(I, J) == -World::Inferences::compare_inferences(J, I)</span>
</pre>
<p class="inwebparagraph">for all pairs of inference pointers <code class="display"><span class="extract">I</span></code> and <code class="display"><span class="extract">J</span></code>.
</p>
<p class="inwebparagraph">More importantly, though, it measures how similar the two inferences are,
because the return value is always plus or minus one of the following.
The notation <code class="display"><span class="extract">CI_DIFFER_IN_WHATEVER</span></code> means that the two inferences do
not differ on all lower-order tests; thus, the higher the absolute value,
the more similar the inferences are. (<code class="display"><span class="extract">CI_IDENTICAL</span></code>, 0, is a special case;
this is returned only when the two inferences are literally the same
structure, i.e., <code class="display"><span class="extract">I == J</span></code>. Merely containing identical data is not enough.)
</p>
<p class="inwebparagraph">By convention, a pair of attached either/or properties which are negations of
each other &mdash; say "open" and "closed" &mdash; are treated as if they were the
same property but with different values.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_EXISTENCE</span><span class="plain"> </span><span class="constant">1</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_TYPE</span><span class="plain"> </span><span class="constant">2</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_PROPERTY</span><span class="plain"> </span><span class="constant">3</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_INFS2</span><span class="plain"> </span><span class="constant">4</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_INFS1</span><span class="plain"> </span><span class="constant">5</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_PROPERTY_VALUE</span><span class="plain"> </span><span class="constant">6</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_DIFFER_IN_COPY_ONLY</span><span class="plain"> </span><span class="constant">7</span>
<span class="definitionkeyword">define</span> <span class="constant">CI_IDENTICAL</span><span class="plain"> </span><span class="constant">0</span>
</pre>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>Funny story: until 2019, this routine ran by using pointer subtraction when
comparing, for example, the INFS references in the inferences, on the principle
that the ordering doesn't really matter so long as it is definite and stable
during a run. But in the late 2010s, desktop operating systems such as MacOS
Mojave began to randomize the address space of all executables, to make it
harder for attackers to exploit buffer overflow bugs. As a result, although
the following routine continued to make definite orderings, they would be
randomly different from one run to another. Inform's output remained
functionally correct, but the generated I6 code would subtly differ from
run to run. And so we instead now incur the cost of looking up allocation IDs,
and indeed of storing those for inference structures.
</p>
<p class="inwebparagraph">Pointer subtraction is, in any case, frowned on in all the best houses, so this
was probably a good thing.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::compare_inferences</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i1</span><span class="plain">, </span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i2</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i1</span><span class="plain"> == </span><span class="identifier">i2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_IDENTICAL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i1</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="constant">CI_DIFFER_IN_EXISTENCE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i2</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="constant">CI_DIFFER_IN_EXISTENCE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> - </span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="identifier">inference_type</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_TYPE</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_TYPE</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">pr1</span><span class="plain"> = </span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">;</span>
<span class="reserved">property</span><span class="plain"> *</span><span class="identifier">pr2</span><span class="plain"> = </span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pr1</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">pr1</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">pr2</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Properties::is_either_or</span><span class="plain">(</span><span class="identifier">pr2</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">pr1</span><span class="plain"> == </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">pr2</span><span class="plain">)) ||</span>
<span class="plain">(</span><span class="identifier">pr2</span><span class="plain"> == </span><span class="functiontext">Properties::EitherOr::get_negation</span><span class="plain">(</span><span class="identifier">pr1</span><span class="plain">)))) </span><span class="identifier">pr2</span><span class="plain"> = </span><span class="identifier">pr1</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_property</span><span class="plain">(</span><span class="identifier">pr1</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_property</span><span class="plain">(</span><span class="identifier">pr2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_PROPERTY</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_PROPERTY</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_infs</span><span class="plain">(</span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_infs</span><span class="plain">(</span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_INFS2</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_INFS2</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_infs</span><span class="plain">(</span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_infs</span><span class="plain">(</span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_INFS1</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_INFS1</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_pn</span><span class="plain">(</span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_pn</span><span class="plain">(</span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_INFS2</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_INFS2</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_pn</span><span class="plain">(</span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_pn</span><span class="plain">(</span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_INFS1</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_INFS1</span><span class="plain">;</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::measure_inf</span><span class="plain">(</span><span class="identifier">i1</span><span class="plain">) - </span><span class="functiontext">World::Inferences::measure_inf</span><span class="plain">(</span><span class="identifier">i2</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val1</span><span class="plain"> = </span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val2</span><span class="plain"> = </span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i1</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain"> != </span><span class="identifier">i2</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">val1</span><span class="plain">) &amp;&amp; (</span><span class="identifier">val2</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Rvalues::compare_CONSTANT</span><span class="plain">(</span><span class="identifier">val1</span><span class="plain">, </span><span class="identifier">val2</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">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_PROPERTY_VALUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_PROPERTY_VALUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_DIFFER_IN_COPY_ONLY</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> -</span><span class="constant">CI_DIFFER_IN_COPY_ONLY</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">CI_IDENTICAL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::measure_property</span><span class="plain">(</span><span class="reserved">property</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">P</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> + </span><span class="identifier">P</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::measure_inf</span><span class="plain">(</span><span class="reserved">inference</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">I</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> + </span><span class="identifier">I</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::measure_infs</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">IS</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">IS</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">1</span><span class="plain"> + </span><span class="identifier">IS</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">World::Inferences::measure_pn</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</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="constant">1</span><span class="plain"> + </span><span class="identifier">N</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">infs_diversion</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::diversion_on</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">infs_diversion</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::diversion_off</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">infs_diversion</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs_diversion</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">I_yourself</span><span class="plain">) &amp;&amp; (</span><span class="identifier">player_VAR</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">infs</span><span class="plain"> == </span><span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">I_yourself</span><span class="plain">))) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">val</span><span class="plain"> = </span><span class="functiontext">NonlocalVariables::get_initial_value</span><span class="plain">(</span><span class="identifier">player_VAR</span><span class="plain">);</span>
<span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">divert</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::from_specification</span><span class="plain">(</span><span class="identifier">val</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">divert</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">divert</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">infs</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::compare_inferences is used in <a href="#SP20">&#167;20</a>.</p>
<p class="endnote">The function World::Inferences::measure_property appears nowhere else.</p>
<p class="endnote">The function World::Inferences::measure_inf appears nowhere else.</p>
<p class="endnote">The function World::Inferences::measure_infs appears nowhere else.</p>
<p class="endnote">The function World::Inferences::measure_pn appears nowhere else.</p>
<p class="endnote">The function World::Inferences::diversion_on appears nowhere else.</p>
<p class="endnote">The function World::Inferences::diversion_off is used in 26/pc (<a href="26-pc.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function World::Inferences::divert_infs is used in <a href="#SP8">&#167;8</a>, <a href="#SP10">&#167;10</a>, <a href="#SP13">&#167;13</a>, <a href="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Joining an inference to what is known about an object. </b>As the above will have made clear, it is not altogether easy to join a new
inference to the linked list of inferences which belong to a given subject: we
can't simply put it at the end of the list. The following routine looks simple
enough, but was a difficult one to get right.
</p>
<p class="inwebparagraph">The loop here completes if and only if the inference is safely joined to the
list; that is, if it is found to contradict or duplicate existing knowledge,
then the routine exits without completing the loop.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::join_inference</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">) {</span>
<span class="constant">PROTECTED_MODEL_PROCEDURE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"joining null inference"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">infs</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">"joining to null inference subject"</span><span class="plain">);</span>
<span class="identifier">infs</span><span class="plain"> = </span><span class="functiontext">World::Inferences::divert_infs</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">inserted</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">list</span><span class="plain">, *</span><span class="identifier">prev</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">list</span><span class="plain"> = </span><span class="functiontext">InferenceSubjects::get_inferences</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">);</span>
<span class="plain">(</span><span class="identifier">list</span><span class="plain">) &amp;&amp; (</span><span class="identifier">inserted</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">); </span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">, </span><span class="identifier">list</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">World::Inferences::compare_inferences</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">list</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">c</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">d</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">icl</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">icl</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">icl</span><span class="plain"> = -</span><span class="identifier">icl</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lcl</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lcl</span><span class="plain"> &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">lcl</span><span class="plain"> = -</span><span class="identifier">lcl</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">affinity_threshold</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Determine the affinity threshold, which depends on the inference type</span> <span class="cwebmacronumber">20.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> &gt;= </span><span class="identifier">affinity_threshold</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">These relate to the same basic fact and one must exclude the other</span> <span class="cwebmacronumber">20.3</span>&gt;<span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">&lt;0) </span>&lt;<span class="cwebmacro">Insert the newly-drawn inference before this list position</span> <span class="cwebmacronumber">20.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">inserted</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Insert the newly-drawn inference before this list position</span> <span class="cwebmacronumber">20.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"drawn"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> == </span><span class="constant">PROPERTY_INF</span><span class="plain">)</span>
<span class="functiontext">Plugins::Call::property_value_notify</span><span class="plain">(</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::join_inference is used in <a href="#SP9">&#167;9</a>, <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP20_1"></a><b>&#167;20.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Insert the newly-drawn inference before this list position</span> <span class="cwebmacronumber">20.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">InferenceSubjects::set_inferences</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">prev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">; </span><span class="identifier">inserted</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="#SP20">&#167;20</a> (twice).</p>
<p class="inwebparagraph"><a id="SP20_2"></a><b>&#167;20.2. </b>The first question we must answer is when our two inferences are talking
about what is basically the same fact. We do this by requiring that the
absolute value of the <code class="display"><span class="extract">World::Inferences::compare_inferences</span></code> score &mdash; which will always be
one of the <code class="display"><span class="extract">CI_*</span></code> constants enumerated above &mdash; must exceed some threshold.
(Recall that higher scores mean greater similarity; the perfect <code class="display"><span class="extract">CI_IDENTICAL</span></code>
is not possible here.)
</p>
<p class="inwebparagraph">The threshold depends on what type of inference we're looking at, but it's
always at least half-way down the list, so we can be certain that
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">i-&gt;inference_type == list-&gt;inference_type</span>
</pre>
<p class="inwebparagraph">(and therefore it's unambiguous what we mean by the type of inference being
looked at). For two property inferences to be talking about the same fact,
they might still differ in the property value &mdash; one might say the carrying
capacity of a table is 10 and the other that it's 15, for example &mdash; so
the threshold is set low enough for a score of <code class="display"><span class="extract">CI_DIFFER_IN_PROPERTY_VALUE</span></code>
still to get in. But with an arbitrary relation threshold, two inferences
never talk about the same fact unless they're essentially identical.
</p>
<p class="inwebparagraph">We set the affinity threshold purposely low for customised inferences
belonging to plugins (at present, anyway).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Determine the affinity threshold, which depends on the inference type</span> <span class="cwebmacronumber">20.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_INF:</span><span class="plain"> </span><span class="identifier">affinity_threshold</span><span class="plain"> = </span><span class="constant">CI_DIFFER_IN_PROPERTY_VALUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ARBITRARY_RELATION_INF:</span><span class="plain"> </span><span class="identifier">affinity_threshold</span><span class="plain"> = </span><span class="constant">CI_DIFFER_IN_COPY_ONLY</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">affinity_threshold</span><span class="plain"> = </span><span class="constant">CI_DIFFER_IN_INFS1</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="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_3"></a><b>&#167;20.3. </b>So, let's suppose our new inference <code class="display"><span class="extract">i</span></code> is sufficiently close to the our
existing one, <code class="display"><span class="extract">list</span></code>. What then?
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">These relate to the same basic fact and one must exclude the other</span> <span class="cwebmacronumber">20.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">icl</span><span class="plain"> != </span><span class="identifier">lcl</span><span class="plain">) </span>&lt;<span class="cwebmacro">They have different certainties, so take the more certain to be true</span> <span class="cwebmacronumber">20.3.1</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">contradiction_flag</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">They are equally certain, so determine whether or not they contradict each other</span> <span class="cwebmacronumber">20.3.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">contradiction_flag</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">icl</span><span class="plain"> == </span><span class="identifier">CERTAIN_CE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Contradictions of certainty are forbidden, so issue a problem</span> <span class="cwebmacronumber">20.3.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">icl</span><span class="plain"> == </span><span class="identifier">LIKELY_CE</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">InferenceSubjects::get_default_certainty</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">) == </span><span class="identifier">LIKELY_CE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Later uncertain data beats earlier, for subjects which generalise about whole domains</span> <span class="cwebmacronumber">20.3.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"redundant"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP20_3_1"></a><b>&#167;20.3.1. </b>Where:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">They have different certainties, so take the more certain to be true</span> <span class="cwebmacronumber">20.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lcl</span><span class="plain"> &gt; </span><span class="identifier">icl</span><span class="plain">) {</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"discarded (we already know better)"</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">InferenceSubjects::set_inferences</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">prev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"replaced existing less certain one"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_3">&#167;20.3</a>.</p>
<p class="inwebparagraph"><a id="SP20_3_2"></a><b>&#167;20.3.2. </b>Note that certainties opposite in sign reverse the issue of whether a
contradiction has occurred. The following, after all, do not conflict:
</p>
<blockquote>
<p>The box is always open. The box is never closed.</p>
</blockquote>
<p class="inwebparagraph">These will cause <code class="display"><span class="extract">contradiction_flag</span></code> to be initially set, below, but then
flipped back again because the certainties are opposite.
</p>
<p class="inwebparagraph">With an arbitrary relation inference, contradictions never occur. (Those
are always required to be positive in sense, i.e., with positive certainty,
and so clashed are impossible.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">They are equally certain, so determine whether or not they contradict each other</span> <span class="cwebmacronumber">20.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_INF:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">d</span><span class="plain"> == </span><span class="constant">CI_DIFFER_IN_PROPERTY_VALUE</span><span class="plain">) </span><span class="identifier">contradiction_flag</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Plugins::Call::inferences_contradict</span><span class="plain">(</span><span class="identifier">list</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="identifier">contradiction_flag</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="identifier">certainty</span><span class="plain"> == -</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">certainty</span><span class="plain">) </span><span class="identifier">contradiction_flag</span><span class="plain"> = (</span><span class="identifier">contradiction_flag</span><span class="plain">)?</span><span class="identifier">FALSE:TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_3">&#167;20.3</a>.</p>
<p class="inwebparagraph"><a id="SP20_3_3"></a><b>&#167;20.3.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Contradictions of certainty are forbidden, so issue a problem</span> <span class="cwebmacronumber">20.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"contradiction"</span><span class="plain">);</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">list</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"with"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="identifier">inference_type</span><span class="plain"> != </span><span class="constant">PROPERTY_INF</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> != </span><span class="constant">ARBITRARY_RELATION_INF</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Plugins::Call::explain_contradiction</span><span class="plain">(</span><span class="identifier">list</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="identifier">infs</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">i</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> == </span><span class="constant">PROPERTY_INF</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain"> == </span><span class="identifier">P_variable_initial_value</span><span class="plain">)</span>
<span class="functiontext">Problems::Issue::two_sentences_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_VariableContradiction</span><span class="plain">),</span>
<span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">,</span>
<span class="string">"this looks like a contradiction"</span><span class="plain">,</span>
<span class="string">"because the initial value of this variable seems to be being set "</span>
<span class="string">"in each of these sentences, but with a different outcome."</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="functiontext">Properties::is_value_property</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">)) {</span>
<span class="reserved">binary_predicate</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain"> =</span>
<span class="functiontext">Properties::Valued::get_stored_relation</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">), </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">))) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_relation</span><span class="plain">(3, </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_subject</span><span class="plain">(4, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(5, </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(6, </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_RelationContradiction2</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I'm finding a contradiction at the sentence %1, "</span>
<span class="string">"because it means I can't set up %3. "</span>
<span class="string">"On the one hand, %4 should relate to %5, but on the other "</span>
<span class="string">"hand to %6, and this is a relation which doesn't allow "</span>
<span class="string">"such clashes."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_relation</span><span class="plain">(3, </span><span class="identifier">bp</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_subject</span><span class="plain">(4, </span><span class="identifier">infs</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(5, </span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_spec</span><span class="plain">(6, </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_RelationContradiction</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I'm finding a contradiction at the sentences %1 and %2, "</span>
<span class="string">"because between them they set up rival versions of %3. "</span>
<span class="string">"On the one hand, %4 should relate to %5, but on the other "</span>
<span class="string">"hand to %6, and this is a relation which doesn't allow "</span>
<span class="string">"such clashes."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="functiontext">Problems::Issue::two_sentences_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_PropertyContradiction</span><span class="plain">),</span>
<span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">,</span>
<span class="string">"this looks like a contradiction"</span><span class="plain">,</span>
<span class="string">"because the same property seems to be being set in each of these sentences, "</span>
<span class="string">"but with a different outcome."</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">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain"> == </span><span class="identifier">IS_ROOM_INF</span><span class="plain">) {</span>
<span class="functiontext">Problems::Issue::two_sentences_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WhenIsARoomNotARoom</span><span class="plain">),</span>
<span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">,</span>
<span class="string">"this looks like a contradiction"</span><span class="plain">,</span>
<span class="string">"because apparently something would have to be both a room and not a "</span>
<span class="string">"room at the same time."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="functiontext">Problems::Issue::two_sentences_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_Contradiction</span><span class="plain">),</span>
<span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">inferred_from</span><span class="plain">,</span>
<span class="string">"this looks like a contradiction"</span><span class="plain">,</span>
<span class="string">"which might be because I have misunderstood what was meant to be the subject "</span>
<span class="string">"of one or both of those sentences."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_3">&#167;20.3</a>.</p>
<p class="inwebparagraph"><a id="SP20_3_4"></a><b>&#167;20.3.4. </b>When talking about kinds or kinds of value, we allow new merely likely
information to displace old; but not when talking about specific objects or
values, when the initial information stands. (This is to make it easier for
people to change the effect of extensions which create kinds and specify their
likely properties.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Later uncertain data beats earlier, for subjects which generalise about whole domains</span> <span class="cwebmacronumber">20.3.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">i</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">list</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">InferenceSubjects::set_inferences</span><span class="plain">(</span><span class="identifier">infs</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">); </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">prev</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">infs</span><span class="plain">, </span><span class="string">"replaced existing also only likely one"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20_3">&#167;20.3</a>.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Logging inferences. </b>We keep the debugging log file more than usually well informed about what
goes on with inferences, as there is obviously great potential for mystifying
bugs if inferences are incorrectly ignored.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::report_inference</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">i</span><span class="plain">, </span><span class="reserved">inference_subject</span><span class="plain"> *</span><span class="identifier">infs</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">what_happened</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">INFERENCES</span><span class="plain">, </span><span class="string">":::: %s: $j - $I\n"</span><span class="plain">, </span><span class="identifier">what_happened</span><span class="plain">, </span><span class="identifier">infs</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 World::Inferences::report_inference is used in <a href="#SP20">&#167;20</a>, <a href="#SP20_3">&#167;20.3</a>, <a href="#SP20_3_1">&#167;20.3.1</a>, <a href="#SP20_3_3">&#167;20.3.3</a>, <a href="#SP20_3_4">&#167;20.3.4</a>.</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. </b>And more generally:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::log_kind</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">it</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">it</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">ARBITRARY_RELATION_INF:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"ARBITRARY_RELATION_INF"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PROPERTY_INF:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"PROPERTY_INF"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="functiontext">Plugins::Call::log_inference_type</span><span class="plain">(</span><span class="identifier">it</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">World::Inferences::log</span><span class="plain">(</span><span class="reserved">inference</span><span class="plain"> *</span><span class="identifier">in</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</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">"&lt;null-inference&gt;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="functiontext">World::Inferences::log_kind</span><span class="plain">(</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">inference_type</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-"</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="identifier">certainty</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">IMPOSSIBLE_CE:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Impossible "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNLIKELY_CE:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Unlikely "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">UNKNOWN_CE:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;No information&gt; "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">LIKELY_CE:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Likely "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CERTAIN_CE:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Certain "</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;unknown-certainty&gt;"</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"(%W)"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">inferred_property</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-1:$P"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">inferred_property_value</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-1:$j"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">infs_ref1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-2:$j"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">infs_ref2</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-s1:$P"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">spec_ref1</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-s2:$P"</span><span class="plain">, </span><span class="identifier">in</span><span class="plain">-&gt;</span><span class="element">spec_ref2</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function World::Inferences::log_kind is used in 1/cm (<a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a>).</p>
<p class="endnote">The function World::Inferences::log is used in 1/cm (<a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="16-pp.html">Back to 'Property Permissions'</a></li><li><a href="16-cmw.html">Continue with 'Complete Model World'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>