mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
282 lines
15 KiB
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">★</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">§1. Rounding</a></li><li><a href="#SP2">§2. Conversion To Number</a></li><li><a href="#SP3">§3. Digital Printing</a></li><li><a href="#SP4">§4. Analogue Printing</a></li><li><a href="#SP5">§5. Understanding</a></li><li><a href="#SP6">§6. Relative Time Token</a></li><li><a href="#SP7">§7. Scene Change Machinery Rule</a></li><li><a href="#SP8">§8. During Scene Matching</a></li><li><a href="#SP9">§9. Scene Questions</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§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 >= 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>§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 < 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>§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<0) { print "<no time>"; return; }</span>
|
|
<span class="plain">if (t >= 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 < 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>§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 > 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>§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<length: i++) {</span>
|
|
<span class="plain">switch (at->i) {</span>
|
|
<span class="plain">':': if (flag == false && i>0 && i<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 < 3 || length > 5 || illegal_char) flag = false;</span>
|
|
<span class="plain">if (flag) {</span>
|
|
<span class="plain">for (i=0: at->i~=':': i++, hr=hr*10) hr = hr + at->i - '0';</span>
|
|
<span class="plain">hr = hr/10;</span>
|
|
<span class="plain">for (i++: i<length: i++, mn=mn*10) mn = mn + at->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 < 0) offhour = TryNumber(wn-1);</span>
|
|
<span class="plain">if (offhour < 0 || offhour >= 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 > 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 <= 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 >= 13) return GPR_FAIL;</span>
|
|
<span class="plain">if (second_word == 'to') {</span>
|
|
<span class="plain">mn = ONE_HOUR-mn; hr--; if (hr<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 < 0 || mn >= 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 < 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 >= 24) return -1;</span>
|
|
<span class="plain">if (minute >= ONE_HOUR) return -1;</span>
|
|
<span class="plain">x = hour*ONE_HOUR + minute; if (hour >= 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' && 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>§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 > 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>§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>§8. During Scene Matching. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ DuringSceneMatching prop sc;</span>
|
|
<span class="plain">for (sc=0: sc<NUMBER_SCENES_CREATED: sc++)</span>
|
|
<span class="plain">if ((scene_status-->sc == 1) && (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>§9. Scene Questions. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">[ SceneUtility sc task;</span>
|
|
<span class="plain">if (sc <= 0) return 0;</span>
|
|
<span class="plain">if (task == 1 or 2) {</span>
|
|
<span class="plain">if (scene_endings-->(sc-1) == 0) return RunTimeProblem(RTP_SCENEHASNTSTARTED, sc);</span>
|
|
<span class="plain">} else {</span>
|
|
<span class="plain">if (scene_endings-->(sc-1) <= 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-->(sc-1))%(TWENTY_FOUR_HOURS);</span>
|
|
<span class="plain">2: return scene_started-->(sc-1);</span>
|
|
<span class="plain">3: return (the_time - scene_ended-->(sc-1))%(TWENTY_FOUR_HOURS);</span>
|
|
<span class="plain">4: return scene_ended-->(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>
|
|
|