! ---------------------------------------------------------------------------- ! TimeWait - an Inform library to provide understanding of English time ! strings, and give an enhanced Wait command. Time games only! ! ! Include it just after Grammar. ! (c) Andrew Clover, 1995, but freely usable. Release 3. ! Compatible with Inform 5.5, library 5/12. ! ---------------------------------------------------------------------------- ! The tw_waiting object is a dodgy way of having a global variable without using ! a global (which we can't because we're #included at an inconvenient time). If ! any importantish messages appear, you should give this object 'on', and any ! multiple waits will stop. This is intended for events such as "Bob threatens ! to kill you unless you give him a fish within the next three moves", but not ! each turn messages like "The radio blares out a Hammond organ rendition of the ! Mr. Blobby song". The only point at which it is essential you set this is if ! you move the clock backwards, or forwards 24 hours or more. object tw_waiting "tw"; ! Action routines for Wait command... [ WaitMovesSub i; if (noun==0) "I don't understand how to wait that long."; L__M(##Wait); give tw_waiting ~on; for (i= noun: (i>1) && (deadflag==0) && (tw_waiting hasnt on): i--) { turns--; EndTurnSequence(); DisplayStatus(); #IFV5; DrawStatusLine(); #ENDIF; } if ((tw_waiting has on) && (i>1) && (deadflag==0)) { print "^(waiting stopped)^"; meta= 1; } ]; [ WaitMinsSub i; noun= (the_time+noun); i=noun / 1440; parsed_number=noun % 1440; WaitUntilSub(i+1); ]; [ WaitHoursSub; noun= noun*60; WaitMinsSub(); ]; [ WaitUntilSub i j; parsed_number=(parsed_number-1); if (parsed_number<0) parsed_number=parsed_number+1440; parsed_number=parsed_number % 1440; if (i==0) { if (parsed_number0))&&(tw_waiting hasnt on)&&(deadflag==0)) { j=the_time; turns--; EndTurnSequence(); if (the_time|<"one"-"twenty">|"half"|"quarter" ["minutes"|"minute"] ! "past"|"to" <"1"-"12">|<"one"-"twelve"> ["am"|"pm"] ! b. <"1"-"12">|<"one"-"twelve"> ["o'clock"] ["am"|"pm"] ! c. <"1"-"12">|<"one"-"twelve"> <"0"-"59">|<"one"-"twenty"> ["am"|"pm"] ! d. <"1"-"12">":"<"0"-"59"> ["am"|"pm"] ! e. "midnight"|"midday"|"noon" ! ! If no am/pm is specified, the next time likely to come up is chosen; that is, ! the one that's just ahead of the current time. However, if this happens, the ! tw_waiting object is given the 'general' attribute. Thus you can change the ! time returned by twelve hours in an action like SetClock if necessary. ! ! The next dictionary command is there to allow us to compare a typed string ! with "o'clock", something we can't normally do as it is bounded by single ! quotes. [ ParseTime i j k flg loop dig hr mn; give tw_waiting ~general; i=NextWord(); if (i=='midday' or 'noon' or 'midnight') ! then case (e) applies { if (i=='midnight') hr=0; else hr=12; mn=0; parsed_number=(hr*60+mn); } else { k=(wn-1)*4+1; ! test for case (d) j=parse->k; j=j+buffer; k=parse->(k-1); flg=0; for (loop=0:looploop; if (dig==':') flg=1; } if ((k>2)&&(k<6)&&(flg==1)) ! then case (d) applies { hr=0; mn=0; loop=0; .tw_diglph; dig=j->loop; loop++; if (dig~=':') hr=hr*10; if (dig=='0') { hr=hr+0; jump tw_diglph; } if (dig=='1') { hr=hr+1; jump tw_diglph; } if (dig=='2') { hr=hr+2; jump tw_diglph; } if (dig=='3') { hr=hr+3; jump tw_diglph; } if (dig=='4') { hr=hr+4; jump tw_diglph; } if (dig=='5') { hr=hr+5; jump tw_diglph; } if (dig=='6') { hr=hr+6; jump tw_diglph; } if (dig=='7') { hr=hr+7; jump tw_diglph; } if (dig=='8') { hr=hr+8; jump tw_diglph; } if (dig=='9') { hr=hr+9; jump tw_diglph; } if (dig~=':') return -1; while (looploop; mn=mn*10; if (dig=='0') { mn=mn+0; jump tw_digokm; } if (dig=='1') { mn=mn+1; jump tw_digokm; } if (dig=='2') { mn=mn+2; jump tw_digokm; } if (dig=='3') { mn=mn+3; jump tw_digokm; } if (dig=='4') { mn=mn+4; jump tw_digokm; } if (dig=='5') { mn=mn+5; jump tw_digokm; } if (dig=='6') { mn=mn+6; jump tw_digokm; } if (dig=='7') { mn=mn+7; jump tw_digokm; } if (dig=='8') { mn=mn+8; jump tw_digokm; } if (dig=='9') { mn=mn+9; jump tw_digokm; } return -1; .tw_digokm; loop++; } ! decode digital time } else { j=NextWordStopped(); if ((j=='o^clock' or -1)||(j=='am' or 'pm')) ! then case (c) applies { hr=TryNumber(wn-2); mn=0; if (j~='o^clock') wn--; } else { k=TryNumber(wn-1); if (k~=-1000) ! then case (b) applies { mn=k; hr=TryNumber(wn-2); } else ! well, must be case (a) { mn=TryNumber(wn-2); if (i=='quarter') mn=15; if (i=='twenty-five') mn=25; if (i=='half' or 'thirty') mn=30; if (j=='minute' or 'minutes') j=NextWord(); ! ignore 'minutes' hr=TryNumber(wn); wn++; if (j~='past' or 'to') hr=-1; if (j=='to') { hr--; mn=60-mn; if (hr==0) hr=12; } } } } if ((hr>12)||(hr<1)||(mn>59)||(mn<0)) parsed_number=-1; else { if (hr==12) ! now sort out am/pm hr=0; i=NextWord(); if (i=='pm') hr=hr+12; else if (i~='am') ! am or pm implied, then? { give tw_waiting general; wn--; i=(hr*60+mn); j=((hr+12)*60+mn); i=i-the_time; j=j-the_time; if (i<0) i=i+(24*60); if (j<0) j=j+(24*60); if (i>j) hr=hr+12; } parsed_number=(hr*60+mn); } } if (parsed_number==-1) return -1; else return 1; ]; [ ParseFor i; i= NextWord(); if (i~='for') wn--; return 0; ]; ! Now the grammar for the new Wait actions. ! You can use parsetime in other new actions. For example, you could perhaps ! allow setting of watches, etc. with grammar like: ! ! extend "set" first ! * is_timepiece "to" parsetime -> SetClock; ! ! You may also like to extend wait to allow "Wait for " extend this ! "first" to make this take precedence over "Wait for