diff --git a/Nathanael Nerode/Variable Time Control-v1.i7x b/Nathanael Nerode/Variable Time Control-v1.i7x index ad8e87a4..cf3260a0 100644 --- a/Nathanael Nerode/Variable Time Control-v1.i7x +++ b/Nathanael Nerode/Variable Time Control-v1.i7x @@ -1,16 +1,76 @@ -Version 1.0.240130 of Variable Time Control by Nathanael Nerode begins here. +Version 1.0.240202 of Variable Time Control by Nathanael Nerode begins here. -"Allows individual actions to take a different number of seconds, or no time at all. Also allows the standard time taken per turn to be defined as so many seconds, which can be varied during the course of play". +"Tracks time so that most actions can take specific amounts of time specified by the game author. +Failed/rejected actions take no time by default. Allows tracking time separately in different scenes +to allow for time travel scenarios. Not currently fully functional." -"Based on Variable Time Control by Eric Eve (version 4)." +"Inspired by Variable Time Control by Eric Eve (version 4) and Modified Timekeeping by Daniel Stelzer". -[NOT CURRENTLY FUNCTIONAL.] +[NOT CURRENTLY FULLY FUNCTIONAL.] -Volume - Time Control Mechanism +Volume - Duration Types + +Section - Simple Temporal Duration Type + +[One-part times: 2 seconds, 3 minutes, etc.] +A simple temporal duration is a kind of value. +1 second (singular) specifies a simple temporal duration. +2 seconds (plural) specifies a simple temporal duration. +1 sec specifies a simple temporal duration. +1 secs specifies a simple temporal duration. +[Conflict with builtin time parsing, skip.] +[1 minute (singular) specifies a simple temporal duration scaled up by 60.] +[2 minutes (plural) specifies a simple temporal duration scaled up by 60.] +1 min specifies a simple temporal duration scaled up by 60. +1 mins specifies a simple temporal duration scaled up by 60. +[Conflict with builtin time parsing, skip.] +[1 hour (singular) specifies a simple temporal duration scaled up by 3600.] +[2 hours (plural) specifies a simple temporal duration scaled up by 3600.] +1 hr specifies a simple temporal duration scaled up by 3600. +1 hrs specifies a simple temporal duration scaled up by 3600. +1 day (singular) specifies a simple temporal duration scaled up by 86400. +2 days (plural) specifies a simple temporal duration scaled up by 86400. + +To decide what number is the reduction to seconds of (interval - a simple temporal duration): + decide on interval / 1 sec. + +Section - Two-part Temporal Duration Type + +[Two-part times: 13:07] +A two-part temporal duration is a kind of value. +1:59 specifies a two-part temporal duration with parts hours and minutes. + +To decide what number is the reduction to seconds of (interval - a two-part temporal duration): + let my_hrs be the hours part of interval; + let my_mins be the minutes part of interval; + decide on (my_hrs * 60 * 60) + (my_mins * 60); + +Section - Time Type + +[Inform's default time type. Generated when matching "5 minutes" or "3 hours".] + +To decide what number is the reduction to seconds of (interval - a time): + let my_hrs be the hours part of interval; + let my_mins be the minutes part of interval; + decide on (my_hrs * 60 * 60) + (my_mins * 60); + +Section - Three-part Temporal Duration Type + +[Three-part times -- 3:07:05] +A three-part temporal duration is a kind of value. +1:59:59 specifies a three-part temporal duration with parts hours and minutes and seconds. + +To decide what number is the reduction to seconds of (interval - a three-part temporal duration): + let my_hrs be the hours part of interval; + let my_mins be the minutes part of interval; + let my_secs be the seconds part of interval; + decide on (my_hrs * 60 * 60) + (my_mins * 60) + (my_secs); + +Volume - Datetime Type Chapter - Months and leap years -Section - Month value type +Section - Month-value Type A month-value is a kind of value. The month-values are January, February, March, April, May, June, July, August, September, October, November, December. @@ -72,7 +132,7 @@ to decide which number is the/-- length of (m - a month-value) in year (y - a nu Chapter - Weekdays -Section - Weekday value type +Section - Weekday-value Type A weekday-value is a kind of value. The weekday-values are Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday. @@ -91,40 +151,44 @@ A datetime has a number called minute. A datetime has a number called second. A datetime has a truth state called modified flag. -Section - Advance time +Section - Internal advance time phrases + +[These work with numbers, and implement the truly complex carry scheme which +our standard calendar uses. Game writers should typically call the non-internal +versions in the next section, which take durations as arguments.] -to advance (dt - a datetime) by (x - a number) second/seconds: +to internally advance (dt - a datetime) by (x - a number) second/seconds: let old be the second of dt; let new total be old + x; let carry be new total / 60; let new result be the remainder after dividing new total by 60; now the second of dt is new result; - advance dt by carry minutes; + internally advance dt by carry minutes; now the modified flag of dt is true; -to advance (dt - a datetime) by (x - a number) minute/minutes: +to internally advance (dt - a datetime) by (x - a number) minute/minutes: let old be the minute of dt; let new total be old + x; let carry be new total / 60; let new result be the remainder after dividing new total by 60; now the minute of dt is new result; - advance dt by carry hours; + internally advance dt by carry hours; now the modified flag of dt is true; -to advance (dt - a datetime) by (x - a number) hour/hours: +to internally advance (dt - a datetime) by (x - a number) hour/hours: let old be the hour of dt; let new total be old + x; let carry be new total / 24; let new result be the remainder after dividing new total by 24; now the hour of dt is new result; - advance dt by carry days; + internally advance dt by carry days; now the modified flag of dt is true; -to advance (dt - a datetime) by (x - a number) day/days: +to internally advance (dt - a datetime) by (x - a number) day/days: [First advance the weekdays.] let weekdays to advance be the remainder after dividing x by 7; [Weekdays loop forever.] while weekdays to advance is greater than 0: - advance weekday for dt; + internally advance weekday for dt; decrement weekdays to advance; [Now advance the month and day.] let old be the day of dt; @@ -135,14 +199,14 @@ to advance (dt - a datetime) by (x - a number) day/days: let the month length be the length of current month in year current year; while new total is greater than month length: now new total is new total - month length; - advance dt by 1 month; + internally advance dt by 1 month; now the current month is the month of dt; now the current year is the year of dt; now the month length is the length of current month in year current year; now the day of dt is new total; now the modified flag of dt is true; -to advance weekday for (dt - a datetime): +to internally advance weekday for (dt - a datetime): [This is meant to be used as a subroutine.] [In a fascinating undocumented feature, "weekday-value after" will always loop.] [Same with "before".] @@ -150,52 +214,170 @@ to advance weekday for (dt - a datetime): now the weekday of dt is the weekday-value after old; now the modified flag of dt is true; -to advance (dt - a datetime) by 1 month/months: +to internally advance (dt - a datetime) by 1 month/months: [WARNING: doesn't advance the weekday! This is meant to be used as a subroutine.] [In a fascinating undocumented feature, "month-value after" will always loop.] [Same with "before".] let old be the month of dt; if old is the last value of month-value: [It's December.] - advance dt by 1 year; + internally advance dt by 1 year; now the month of dt is the month-value after old; now the modified flag of dt is true; -to advance (dt - a datetime) by (x - a number) year/years: +to internally advance (dt - a datetime) by (x - a number) year/years: [By far the simplest, and the only one with no carries] let old be the year of dt; let new total be old + x; now the year of dt is new total; now the modified flag of dt is true; -Section - say the time +Section - Advance time phrase for Simple Temporal Duration + +to advance (dt - a datetime) by (interval - a simple temporal duration): + let x be the reduction to seconds of interval; + internally advance dt by x seconds; + +Section - Advance time phrase for Two-part Temporal Duration + +to advance (dt - a datetime) by (interval - a time): + let x be the reduction to seconds of interval; + internally advance dt by x seconds; + +Section - Advance time phrase for Time + +to advance (dt - a datetime) by (interval - a two-part temporal duration): + let x be the reduction to seconds of interval; + internally advance dt by x seconds; + +Section - Advance time phrase for Three-part Temporal Duration + +to advance (dt - a datetime) by (interval - a three-part temporal duration): + let x be the reduction to seconds of interval; + internally advance dt by x seconds; + +Volume - Showing the time + +Section - Validate datetime + +[ Purely for debugging ] +To validate (dt - a datetime): + if the second of dt < 0: + say "Error: second negative [second of dt]."; + if the second of dt > 59: + say "Error: second too large [second of dt]."; + if the minute of dt < 0: + say "Error: minute negative [minute of dt]."; + if the minute of dt > 59: + say "Error: minute too large [minute of dt]."; + if the hour of dt < 0: + say "Error: hour negative [hour of dt]."; + if the hour of dt > 23: + say "Error: hour too large [hour of dt]."; + if the day of dt < 0: + say "Error: day negative [day of dt]."; + if the day of dt > 31: + say "Error: day too large [day of dt]."; + [We don't check each month, since this is just a sanity check] + [Months and weekdays are enums, so they always work.] + [We don't put any limits on year numbers.] + +Section - Say pieces of a datetime + +To say hour for (dt - a datetime) in zulu format: + [00: or 01: rather than 24: or 1:] + if the hour of dt < 10: + say "0"; + say the hour of dt; + +To say hour for (dt - a datetime) in 24 hour format: + [24:00 rather than 0:00] + if the hour of dt is 0: + say "24"; + otherwise: + say the hour of dt; + +To say ampm for (dt - a datetime): + if the hour of dt < 12: + say "AM"; + otherwise: + say "PM"; + +To say hour for (dt - a datetime) in 12 hour format: + [1:00 PM rather than 13:00] + if the hour of dt > 12: + say the hour of dt - 12; + otherwise if the hour of dt is 0: + say "12"; + otherwise: + say the hour of dt; + +To say minutes for (dt - a datetime): + [:05 rather than :5] + if the minute of dt < 10: + say "0"; + say the minute of dt; + +To say seconds for (dt - a datetime): + [:05 rather than :5] + if the second of dt < 10: + say "0"; + say the second of dt; + + +Section - Say a whole datetime [FIXME. This is mostly for testing purposes. To be improved as needed] +[These had to be broken out into subroutines mostly for readability.] + +To say (dt - a datetime) fully: + validate dt; + say "[weekday of dt] [year of dt] [month of dt] [day of dt] "; + say "[hour for dt in 12 hour format]:[minutes for dt]:[seconds for dt] [ampm for dt]"; + [The end.] + +Section - Text substitution for datetime object [The following has to be done instead of 'to say (dt - a datetime)'] Rule for printing the name of a datetime (called dt): say the dt fully; -To say (dt - a datetime) fully: - say "[the weekday of dt] [the year of dt] [the month of dt] [the day of dt] [the hour of dt]:[the minute of dt]:[the second of dt]"; +Section - Showing the time action + +Showing time is an action out of world applying to nothing. + +Report showing time: + say "It is now [the game datetime fully]."; + +Section - Showing the time Understand line (not for release) -Section - default start datetime +[For debugging purposes only] +Understand "time" as showing time. -[Essentially for testing purposes. -This is a real date; it's when I wrote the first version of this extension.] +Volume - Standard Datetimes + +Section - Default Start Datetime object The default start datetime is a datetime. -The year of the default start datetime is 2024. -The month of the default start datetime is January. -The day of the default start datetime is 28. -The weekday of the default start datetime is Sunday. -The hour of the default start datetime is 22. -The minute of the default start datetime is 50. -The second of the default start datetime is 15. +Section - Default Start Datetime Defaults + +[These SHOULD be overridden by the game author.] +[Overrides are not tested. FIXME.] + +[This is a real date; it's when I wrote the first version of this extension.] +The year of the default start datetime is usually 2024. +The month of the default start datetime is usually January. +The day of the default start datetime is usually 28. +The weekday of the default start datetime is usually Sunday. +The hour of the default start datetime is usually 22. +The minute of the default start datetime is usually 50. +The second of the default start datetime is usually 15. Section - Player's real start datetime (for use with Real Date and Time by Ron Newcomb) +[Not implemented. FIXME] + [ The player's real start datetime is a datetime. The year of the player's real start datetime is (- GetNthDateTimeComponent(0) -). @@ -207,44 +389,146 @@ The minute of the player's real start datetime is (- GetNthDateTimeComponent(5) The second of the player's real start datetime is (- GetNthDateTimeComponent(6) -). ] -Section - primary game datetime +Section - Primary Game Datetime + +[This is the initial object which tracks the in-game time and date. +It can be swapped out. See below regarding "game datetime".] The primary game datetime is a datetime which varies. -[Game writer should override] +[Game author should override this for sure. This is just so that there is *some* default.] +[FIXME.] The primary game datetime is usually the default start datetime. -Section - test advance (not for release) +Section - Game Datetime + +[This is the object tracking the datetime of the game right now. +It starts out the same as the "primary game datetime". +This is the one which is updated by the various phrases and actions. + +The reason for this: + +If you have a game set in 1967 and then have a "flashback scene" set in 1795, +you can have the "primary game datetime" start in 1967; then put a different +datetime object into "the game datetime" for the flashback scene, and then when +the player returns to the present day, swap the datetime object back and arrive +"right back when you left". +] + +The game datetime is a datetime which varies. + +Section - Start in Primary Game Datetime + +[ This has to be done in a rule during startup, +because we can't "cascade" usually statements for startup definitions. +It is a very simple assignment so it is quite safe.] + +This is the initialize game datetime rule: + now the game datetime is the primary game datetime. + +[This is done very early, before "position player in model world" and before "start in the correct scenes", +largely so that the game author can override it and replace it immediately in "when play begins", or +indeed in the definition of a scene.] + +The initialize game datetime rule is listed before the position player in model world rule in the after starting the virtual machine rules. + +Volume - Waiting Actions -Advancing the clock it seconds is an action applying to one number. +[These advance the "game datetime".] -Understand "advance [number]" as advancing the clock it seconds. +[Trying to pass from one action to another using "try" fails. +"convert to" only works with objects, not value types. +So this requires redundant implementation.] -Carry out advancing the clock a number (called x) seconds: - advance the primary game datetime by x seconds; - if the primary game datetime is on-stage, say "whoops, primary game datetime shouldn't be onstage"; - if the default start datetime is on-stage, say "whoops, default start datetime shouldn't be onstage"; - say the primary game datetime fully; +Chapter - Simple Temporal Duration -Volume - Default time advancement +Section - Wait For Simple Temporal Duration Understand Clause + +Understand "wait [simple temporal duration]" or "wait for [simple temporal duration]" as advancing time simply. + +Section - Wait for Simple Temporal Duration Action + +Advancing time simply is an action applying to one simple temporal duration. + +Carry out advancing time simply: + advance the game datetime by the simple temporal duration understood. + +Chapter - Two-part Temporal Duration + +Section - Wait For Two-part Temporal Duration Understand Clause + +Understand "wait [time]" or "wait for [time]" as advancing time two-part. + +Section - Wait For Two-part Temporal Duration Action + +Advancing time two-part is an action applying to one time. +Carry out advancing time two-part: + advance the game datetime by the two-part temporal duration understood. + +Chapter - Time Period + +["a time period" is defined in Standard Rules. Handles minutes and hours.] +[Inform 7 confusingly converts this to the "time" type, though it has a different grammar token.] + +Section - Wait for Time Period Understand Clause + +Understand "wait [a time period]" or "wait for [a time period]" as advancing time by a time period. + +Section - Wait for Time Period Action + +Advancing time by a time period is an action applying to one time. + +Carry out advancing time by a time period: + advance the game datetime by the time understood. + +Chapter - Three-part Temporal Duration + +Section - Wait For Three-part Temporal Duration Understand Clause + +Understand "wait [Three-part temporal duration]" or "wait for [Three-part temporal duration]" as advancing time three-part. + +Section - Wait For Three-part Temporal Duration Action + +Advancing time three-part is an action applying to one three-part temporal duration. +Carry out advancing time three-part: + advance the game datetime by the three-part temporal duration understood. + +Chapter - Unified Report for Waiting + +[Use an "after" rule so we only have to write the report once.] + +After advancing time simply, + advancing time two-part, + advancing time by a time period, + or advancing time three-part: + say "It is now [the game datetime fully]."; + +Volume - Standard time advancement Section - Reset modified flag [Reset this very early in the turn sequence.] This is the declare time unmodified rule: - now the modified flag of the primary game datetime is false; + now the modified flag of the game datetime is false; The declare time unmodified rule is listed before the early scene changing stage rule in the turn sequence rulebook. [Immediately after the generate action rule] +Section - Standard time per turn + +[Game author can override to change the length of all turns.] + +The standard time per turn is a simple temporal duration that varies. +[We can't say 1 minute because Core Inform turns that into a "time". Aargh.] +The standard time per turn is usually 60 seconds. + Section - Default time advancement rule -The default seconds per turn is a number that varies. -the default seconds per turn is 60. +[This should only trigger if nothing else advanced time during the turn: hence, default] This is the advance time by default rule: - if the modified flag of the the primary game datetime is false: - advance the primary game datetime by default seconds per turn seconds; + if the modified flag of the the game datetime is false: + advance the game datetime by standard time per turn; [ TODO FIXME: incorporate Modified Timekeeping by Daniel Stelzer to fix implicit actions ] [ He does this: @@ -331,9 +615,9 @@ it has "Stop the Action" in a "Carry Out" rule, which is forbidden and will brea The advance time by default rule is listed last in the carry out talking about rulebook. - Chapter - Time Control Variables +[ time-reset is a truth state that varies. time-reset is false. seconds_used is a truth state that varies. seconds_used is false. @@ -341,10 +625,11 @@ previous_seconds is a number that varies. previous_seconds is 0. seconds_per_turn is a number that varies. seconds_per_turn is 60. seconds is a number that varies. seconds is 0. - +] Chapter - The Variable Advance Time Rule +[ This is the variable advance time rule: if time-reset is true begin; now time-reset is false; @@ -361,12 +646,12 @@ This is the variable advance time rule: The variable advance time rule is listed instead of the advance time rule in the turn sequence rules. - +] Chapter - Time Control Phrases [ Take no time consumes neither time nor turns ] - +[ To take no time: now time-reset is true; now seconds is previous_seconds; @@ -389,12 +674,12 @@ To take (n - a number) sec/secs/second/seconds in/-- all/total/only: now seconds_used is true. To say take/-- (n - a number) sec/secs/second/seconds in/-- all/total/only: take n secs in all. - +] Chapter - Displaying Time with Seconds [ This can be used to display the time of day in the format hh:mm:ss am/pm ] - +[ To say sec-time: let sec_tim be "[time of day]"; let x be word number 2 in sec_tim; @@ -402,7 +687,7 @@ To say sec-time: otherwise let x be "[x]:0[seconds]"; replace word number 2 in sec_tim with x; say "[sec_tim]"; - +] Variable Time Control ends here.