1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/standard_rules/S-tt2.html

282 lines
15 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>S/tt</title>
<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>
<!--Weave of 'S/tt2' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">standard_rules Template Library</a></li><li><b>Time Template</b></li></ul><p class="purpose">Support for parsing and printing times of day.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Rounding</a></li><li><a href="#SP2">&#167;2. Conversion To Number</a></li><li><a href="#SP3">&#167;3. Digital Printing</a></li><li><a href="#SP4">&#167;4. Analogue Printing</a></li><li><a href="#SP5">&#167;5. Understanding</a></li><li><a href="#SP6">&#167;6. Relative Time Token</a></li><li><a href="#SP7">&#167;7. Scene Change Machinery Rule</a></li><li><a href="#SP8">&#167;8. During Scene Matching</a></li><li><a href="#SP9">&#167;9. Scene Questions</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Rounding. </b>The following rounds a numerical value <code class="display"><span class="extract">t1</span></code> to the nearest unit of <code class="display"><span class="extract">t2</span></code>;
for instance, if <code class="display"><span class="extract">t2</span></code> is 5 then it rounds to the nearest 5. The name is an
anachronism, as it's used for all kinds of value.
</p>
<pre class="display">
<span class="plain">[ RoundOffTime t1 t2;</span>
<span class="plain">if (t1 &gt;= 0) return ((t1+t2/2)/t2)*t2;</span>
<span class="plain">return -((-t1+t2/2)/t2)*t2;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. Conversion To Number. </b></p>
<pre class="display">
<span class="plain">[ NUMBER_TY_to_TIME_TY n;</span>
<span class="plain">n = n%1440;</span>
<span class="plain">if (n &lt; 0) return n + 1440;</span>
<span class="plain">return n;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. Digital Printing. </b>For instance, "2:06 am".
</p>
<pre class="display">
<span class="plain">[ PrintTimeOfDay t h aop;</span>
<span class="plain">if (t&lt;0) { print "&lt;no time&gt;"; return; }</span>
<span class="plain">if (t &gt;= TWELVE_HOURS) { aop = "pm"; t = t - TWELVE_HOURS; } else aop = "am";</span>
<span class="plain">h = t/ONE_HOUR; if (h==0) h=12;</span>
<span class="plain">print h, ":";</span>
<span class="plain">if (t%ONE_HOUR &lt; 10) print "0"; print t%ONE_HOUR, " ", (string) aop;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Analogue Printing. </b>For instance, "six minutes past two".
</p>
<pre class="display">
<span class="plain">[ PrintTimeOfDayEnglish t h m dir aop;</span>
<span class="plain">h = (t/ONE_HOUR) % 12; m = t%ONE_HOUR; if (h==0) h=12;</span>
<span class="plain">if (m==0) { print (number) h, " o'clock"; return; }</span>
<span class="plain">dir = "past";</span>
<span class="plain">if (m &gt; HALF_HOUR) { m = ONE_HOUR-m; h = (h+1)%12; if (h==0) h=12; dir = "to"; }</span>
<span class="plain">switch(m) {</span>
<span class="plain">QUARTER_HOUR: print "quarter"; HALF_HOUR: print "half";</span>
<span class="plain">default: print (number) m;</span>
<span class="plain">if (m%5 ~= 0) {</span>
<span class="plain">if (m == 1) print " minute"; else print " minutes";</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">print " ", (string) dir, " ", (number) h;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Understanding. </b>This I6 grammar token converts words in the player's command to a valid
I7 time, and is heavily based on the one presented as a solution to an
exercise in the DM4.
</p>
<pre class="display">
<span class="plain">[ TIME_TOKEN first_word second_word at length flag</span>
<span class="plain">illegal_char offhour hr mn i original_wn;</span>
<span class="plain">original_wn = wn;</span>
<span class="plain">i = TIME_TOKEN_INNER();</span>
<span class="plain">if (i ~= GPR_FAIL) return i;</span>
<span class="plain">wn = original_wn;</span>
<span class="plain">first_word = NextWordStopped();</span>
<span class="plain">switch (first_word) {</span>
<span class="plain">'midnight': parsed_number = 0; return GPR_NUMBER;</span>
<span class="plain">'midday', 'noon': parsed_number = TWELVE_HOURS;</span>
<span class="plain">return GPR_NUMBER;</span>
<span class="plain">}</span>
<span class="plain">! Next try the format 12:02</span>
<span class="plain">at = WordAddress(wn-1); length = WordLength(wn-1);</span>
<span class="plain">for (i=0: i&lt;length: i++) {</span>
<span class="plain">switch (at-&gt;i) {</span>
<span class="plain">':': if (flag == false &amp;&amp; i&gt;0 &amp;&amp; i&lt;length-1) flag = true;</span>
<span class="plain">else illegal_char = true;</span>
<span class="plain">'0', '1', '2', '3', '4', '5', '6', '7', '8', '9': ;</span>
<span class="plain">default: illegal_char = true;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">if (length &lt; 3 || length &gt; 5 || illegal_char) flag = false;</span>
<span class="plain">if (flag) {</span>
<span class="plain">for (i=0: at-&gt;i~=':': i++, hr=hr*10) hr = hr + at-&gt;i - '0';</span>
<span class="plain">hr = hr/10;</span>
<span class="plain">for (i++: i&lt;length: i++, mn=mn*10) mn = mn + at-&gt;i - '0';</span>
<span class="plain">mn = mn/10;</span>
<span class="plain">second_word = NextWordStopped();</span>
<span class="plain">parsed_number = HoursMinsWordToTime(hr, mn, second_word);</span>
<span class="plain">if (parsed_number == -1) return GPR_FAIL;</span>
<span class="plain">if (second_word ~= 'pm' or 'am') wn--;</span>
<span class="plain">return GPR_NUMBER;</span>
<span class="plain">}</span>
<span class="plain">! Lastly the wordy format</span>
<span class="plain">offhour = -1;</span>
<span class="plain">if (first_word == 'half') offhour = HALF_HOUR;</span>
<span class="plain">if (first_word == 'quarter') offhour = QUARTER_HOUR;</span>
<span class="plain">if (offhour &lt; 0) offhour = TryNumber(wn-1);</span>
<span class="plain">if (offhour &lt; 0 || offhour &gt;= ONE_HOUR) return GPR_FAIL;</span>
<span class="plain">second_word = NextWordStopped();</span>
<span class="plain">switch (second_word) {</span>
<span class="plain">! "six o'clock", "six"</span>
<span class="plain">'o^clock', 'am', 'pm', -1:</span>
<span class="plain">hr = offhour; if (hr &gt; 12) return GPR_FAIL;</span>
<span class="plain">! "quarter to six", "twenty past midnight"</span>
<span class="plain">'to', 'past':</span>
<span class="plain">mn = offhour; hr = TryNumber(wn);</span>
<span class="plain">if (hr &lt;= 0) {</span>
<span class="plain">switch (NextWordStopped()) {</span>
<span class="plain">'noon', 'midday': hr = 12;</span>
<span class="plain">'midnight': hr = 0;</span>
<span class="plain">default: return GPR_FAIL;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">if (hr &gt;= 13) return GPR_FAIL;</span>
<span class="plain">if (second_word == 'to') {</span>
<span class="plain">mn = ONE_HOUR-mn; hr--; if (hr&lt;0) hr=23;</span>
<span class="plain">}</span>
<span class="plain">wn++; second_word = NextWordStopped();</span>
<span class="plain">! "six thirty"</span>
<span class="plain">default:</span>
<span class="plain">hr = offhour; mn = TryNumber(--wn);</span>
<span class="plain">if (mn &lt; 0 || mn &gt;= ONE_HOUR) return GPR_FAIL;</span>
<span class="plain">wn++; second_word = NextWordStopped();</span>
<span class="plain">}</span>
<span class="plain">parsed_number = HoursMinsWordToTime(hr, mn, second_word);</span>
<span class="plain">if (parsed_number &lt; 0) return GPR_FAIL;</span>
<span class="plain">if (second_word ~= 'pm' or 'am' or 'o^clock') wn--;</span>
<span class="plain">return GPR_NUMBER;</span>
<span class="plain">];</span>
<span class="plain">[ HoursMinsWordToTime hour minute word x;</span>
<span class="plain">if (hour &gt;= 24) return -1;</span>
<span class="plain">if (minute &gt;= ONE_HOUR) return -1;</span>
<span class="plain">x = hour*ONE_HOUR + minute; if (hour &gt;= 13) return x;</span>
<span class="plain">x = x % TWELVE_HOURS; if (word == 'pm') x = x + TWELVE_HOURS;</span>
<span class="plain">if (word ~= 'am' or 'pm' &amp;&amp; hour == 12) x = x + TWELVE_HOURS;</span>
<span class="plain">return x;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Relative Time Token. </b>"Time" is an interesting kind of value since it can hold two conceptually
different ways of thinking about time: absolute times, such as "12:03 PM",
and also relative times, like "ten minutes". For parsing purposes, these
are completely different from each other, and the time token above handles
only absolute times; we need the following for relative ones.
</p>
<pre class="display">
<span class="plain">[ RELATIVE_TIME_TOKEN first_word second_word offhour mult mn original_wn;</span>
<span class="plain">original_wn = wn;</span>
<span class="plain">wn = original_wn;</span>
<span class="plain">first_word = NextWordStopped(); wn--;</span>
<span class="plain">if (first_word == 'an' or 'a//') mn=1; else mn=TryNumber(wn);</span>
<span class="plain">if (mn == -1000) {</span>
<span class="plain">first_word = NextWordStopped();</span>
<span class="plain">if (first_word == 'half') offhour = HALF_HOUR;</span>
<span class="plain">if (first_word == 'quarter') offhour = QUARTER_HOUR;</span>
<span class="plain">if (offhour &gt; 0) {</span>
<span class="plain">second_word = NextWordStopped();</span>
<span class="plain">if (second_word == 'of') second_word = NextWordStopped();</span>
<span class="plain">if (second_word == 'an') second_word = NextWordStopped();</span>
<span class="plain">if (second_word == 'hour') {</span>
<span class="plain">parsed_number = offhour;</span>
<span class="plain">return GPR_NUMBER;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">return GPR_FAIL;</span>
<span class="plain">}</span>
<span class="plain">wn++;</span>
<span class="plain">first_word = NextWordStopped();</span>
<span class="plain">switch (first_word) {</span>
<span class="plain">'minutes', 'minute': mult = 1;</span>
<span class="plain">'hours', 'hour': mult = 60;</span>
<span class="plain">default: return GPR_FAIL;</span>
<span class="plain">}</span>
<span class="plain">parsed_number = mn*mult;</span>
<span class="plain">if (mult == 60) {</span>
<span class="plain">mn=TryNumber(wn);</span>
<span class="plain">if (mn ~= -1000) {</span>
<span class="plain">wn++;</span>
<span class="plain">first_word = NextWordStopped();</span>
<span class="plain">if (first_word == 'minutes' or 'minute')</span>
<span class="plain">parsed_number = parsed_number + mn;</span>
<span class="plain">else wn = wn - 2;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">return GPR_NUMBER;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Scene Change Machinery Rule. </b></p>
<pre class="display">
<span class="plain">[ SCENE_CHANGE_MACHINERY_R;</span>
<span class="plain">DetectSceneChange();</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. During Scene Matching. </b></p>
<pre class="display">
<span class="plain">[ DuringSceneMatching prop sc;</span>
<span class="plain">for (sc=0: sc&lt;NUMBER_SCENES_CREATED: sc++)</span>
<span class="plain">if ((scene_status--&gt;sc == 1) &amp;&amp; (prop(sc+1))) rtrue;</span>
<span class="plain">rfalse;</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Scene Questions. </b></p>
<pre class="display">
<span class="plain">[ SceneUtility sc task;</span>
<span class="plain">if (sc &lt;= 0) return 0;</span>
<span class="plain">if (task == 1 or 2) {</span>
<span class="plain">if (scene_endings--&gt;(sc-1) == 0) return RunTimeProblem(RTP_SCENEHASNTSTARTED, sc);</span>
<span class="plain">} else {</span>
<span class="plain">if (scene_endings--&gt;(sc-1) &lt;= 1) return RunTimeProblem(RTP_SCENEHASNTENDED, sc);</span>
<span class="plain">}</span>
<span class="plain">switch (task) {</span>
<span class="plain">1: return (the_time - scene_started--&gt;(sc-1))%(TWENTY_FOUR_HOURS);</span>
<span class="plain">2: return scene_started--&gt;(sc-1);</span>
<span class="plain">3: return (the_time - scene_ended--&gt;(sc-1))%(TWENTY_FOUR_HOURS);</span>
<span class="plain">4: return scene_ended--&gt;(sc-1);</span>
<span class="plain">}</span>
<span class="plain">];</span>
</pre>
<p class="inwebparagraph"></p>
<hr class="tocbar">
<ul class="toc"><li><a href="S-tt.html">Back to 'Tests Template'</a></li><li><a href="S-wt.html">Continue with 'WorldModel Template'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>