It all began with an effort to replicate the I5 scenery.h extension by Joe Mason, which provided an elegant solution to provide verbose descriptions of non-object scenery mentioned in room descriptions.
The original seems to have been overtaken by developments in parser dependencies even with the advent of I6, never mind I7. Maybe everyone just implements multiple scenery objects nowadays.
Anyway, the idea is to have a nice table of verbose non-object scenery descriptions for each room. The (possibly crazy) way I hit on of implementing this was to have a ‘dummy object’ which temporarily stood in as a scenery object every time the player referred to something mentioned in the ‘Table of Scenery’; setting appropriate printed name, description and plural named properties; then substitute the name of this dummy object for the ‘virtual scenery’ the player had actually typed in the command.
So for example ‘examine rosebed’ would become ‘examine sobj’ and sobj would have the printed name “rosebed” the description “A riot of floral colour” and be singular-named.
In practice, this approach has led to snowballing difficulties separate to the parser problem, such as keeping pronouns working, and I ended up implementing two objects, one for singular named and one for plural named scenery, a fix to avoid confusing the parser by manipulating the command at the scoping stage, code to deal with the player doing things other than examining the scenery etc. etc. and I do wonder if there is a fundamentally better way of tackling this.
Regarding the parser issue, your suggestion of a ‘For reading a command rule’ is certainly more elegant than the one I hit on, and returns the command line manipulation to its proper place in the turn sequence.
"A Scenic View" by PB
Book 1 - Setup
Part 1 - Out-of-World Setup
Chapter 1 - When Play Begins
When play begins:
[now scenery_debug_1 is true;]
[now scenery_debug_2 is true;]
[now command_debug_1 is true;]
continue the action;
Chapter 2 - Every Turn
[[Every turn]]
Every turn:
[scenery handling]
now the sobj is nowhere;
now the pobj is nowhere;
if command_debug_1 is true:
say "Every turn runs....";
say "Original typed command- [original command typed] This turn's command- [player's command][line break]";
Chapter 3 - Global Variables
command_debug_1 is a truth state that varies. command_debug_1 is usually false.
scenery_debug_1 is a truth state that varies. scenery_debug_1 is usually false.
scenery_debug_2 is a truth state that varies. scenery_debug_2 is usually false.
Chapter 4 - Scenery
Section 1 - Definitions
[[Scenery]]
A room has a table name called the detailed scenery. The detailed scenery is usually the Table of Default Scenery.
Table of Default Scenery
topic plural description
"default" false "It's really just scenery"
The sobj is scenery.
The pobj is scenery. It is plural-named.
The original command typed is a text that varies. [original command typed, including all multiple commands]
The matched_description is a text that varies.
The provisional_action is an action that varies.
singular_matching_scenery is a truth state that varies. [flag for having matched a singular-named piece of scenery]
plural_matching_scenery is a truth state that varies. [flag for having matched a plural-named piece of scenery]
match_count is a number that varies [counts the number of scenery matches made during iterations]
Section 2 - Processing the Command
Before reading a command:
if command_debug_1 is true:
say "Reading command....";
say "Previous typed command- [original command typed] Last turn translation- [player's command][line break]";
now the original command typed is "";
After reading a command:
If the original command typed is "":
let snp be the player's command;
[need to use a temporary variable copy of a snippet to force a deep copy casting to text]
now the original command typed is "[snp]"; [casts a permanent copy to type text]
Before deciding the scope of the player (this is the scenery substitution rule): [can't do this after reading command as it fails to run again for each command if there are multiple commands typed into one line]
if scenery_debug_2 is true or command_debug_1 is true, say "Processing command: [the player's command][line break]";
now singular_matching_scenery is false;
now plural_matching_scenery is false;
now the matched_description is "##none##";
now the match_count is 0;
repeat with iteration running from 1 to 2:
if scenery_debug_2 is true, say "iteration [iteration][line break]";
repeat through the detailed scenery of the location:
if the player's command includes the topic entry: [we have a potential match]
unless "[matched text]" is quoted in the immediate command:
next; [deal with multiple commands on one line by rejecting any not in the immediate command]
increment the match_count; [match found, so continue]
if scenery_debug_1 is true, say "matched [description entry][line break]";
if scenery_debug_1 is true, say "[matched text]";
now the matched_description is the description entry;
if the plural entry is true:
now plural_matching_scenery is true;
now the description of the pobj is the matched_description;
now the printed name of the pobj is the matched text;
replace the matched text with "[padpluralmatchedwords]pobj"; [need to replace with same number of words or parser gets confused when already at stage of deciding scope]
set pronouns from the pobj;
otherwise:
now singular_matching_scenery is true;
now the description of the sobj is the matched_description;
now the printed name of the sobj is the matched text;
replace the matched text with "[padsingularmatchedwords]sobj"; [need to replace with same number of words or parser gets confused when already at stage of deciding scope]
set pronouns from the sobj;
if scenery_debug_1 is true, announce_pronouns;
if match_count is 0:
break; [no match so no point repeating]
if the player's command includes "them":
if scenery_debug_1 is true, say "the them object is [the them_object].";
if the them_object is the pobj:
if "them" is quoted in the immediate command:
increment the match_count;
now plural_matching_scenery is true;
[set pronouns from the scenic_object;]
if scenery_debug_1 is true, announce_pronouns;
if the player's command includes "it":
if scenery_debug_1 is true, say "the it object is [the it_object].";
if the it_object is the sobj:
if "it" is quoted in the immediate command:
increment the match_count;
now singular_matching_scenery is true;
[set pronouns from the scenic_object;]
if scenery_debug_1 is true, announce_pronouns;
[continue the activity;]
[Before deciding the scope of the player:]
if singular_matching_scenery is true:
move sobj to location;
if plural_matching_scenery is true:
move pobj to location;
if scenery_debug_2 is true, say "(trying [player's command])[line break]";
continue the activity;
Section 3 - Supporting Functions
To say padpluralmatchedwords:
let N be the number of punctuated words in the matched text;
if N > 1:
repeat with S running from 2 to N:
say "pobj ";
To say padsingularmatchedwords:
let N be the number of punctuated words in the matched text;
if N > 1:
repeat with S running from 2 to N:
say "sobj ";
To decide whether (T - some text) is quoted in the immediate command:
if scenery_debug_2 is true, say "potential match for '[T]'[line break]";
[check that it occurs before the first period '.' or 'then']
let cmd_text be "[the player's command]";
let match_text be "[T]";
let match_found be false;
let word_match be 0;
repeat with word_index running from 1 to number of punctuated words in cmd_text:
if scenery_debug_2 is true, say "trying command word [word_index]; ";
let match_found be true; [try to find a match at this position in cmd_text]
if punctuated word number word_index in cmd_text exactly matches the regular expression "\.|then":
if scenery_debug_2 is true, say ". or then found at position [word_index][line break]";
now match_found is false;
break;[not a match in the first phrase]
else:
repeat with match_index running from 1 to number of punctuated words in match_text:
if scenery_debug_2 is true, say "trying matched word [match_index] '[word number match_index in match_text]'; ";
if punctuated word number (word_index + match_index - 1) in cmd_text exactly matches the text word number match_index in match_text:
if scenery_debug_2 is true, say "matched; ";
next;
else:
now match_found is false;
break; [not a match, try next word posiion in cmd_text]
now word_match is word_index; [final word position tried]
if scenery_debug_2 is true, say "[line break]";
if match_found is true:
break;
if match_found is false:
decide no; [no match for this entry in the scenery table, so try next]
if scenery_debug_2 is true, say "match for '[T]' found at word [word_match][line break]";
decide yes;
After deciding the scope of the player:
now the provisional_action is the current action;
Chapter 5 - Generic Action Interventions
[[Actions Generic]]
Before doing something:
if the match_count is greater than 1: [reject multiple references to different items of scenery]
[[SPECIAL CASES]]
if the provisional_action is examining nothing: [special case for EXAMINING. nouns are set to nothing at scoping stage]
say "I couldn't fully understand what [we] [are] wanting to look at." instead;
else: [GENERIC RESPONSE]
say "[We] [are] best not interfering too much with the scenery." instead;
stop the action;
Part 2 - Pronouns
[[Pronouns]]
[! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
! Pronoun Functions
! ==== ==== ==== ==== ==== ==== ==== ==== ==== ====]
To announce_pronouns: (- ANNOUNCE_PRONOUN_MEANINGS_R(); -)
Include
(- [ GET_PRONOUN_OBJ_R x ;
return LanguagePronouns-->(x*3);
]; -)
Include
(- [ SET_PRONOUN_OBJ_R y x ;
LanguagePronouns-->(x*3) = y;
]; -)
To set the it object to (O - an object):
(- SET_PRONOUN_OBJ_R( {O}, 1 ); -)
To set the him object to (O - an object):
(- SET_PRONOUN_OBJ_R( {O}, 2 ); -)
To set the her object to (O - an object):
(- SET_PRONOUN_OBJ_R( {O}, 3 ); -)
To set the them object to (O - an object):
(- SET_PRONOUN_OBJ_R( {O}, 4 ); -)
To decide which object is the it_object:
(- GET_PRONOUN_OBJ_R(1) -)
To decide which object is the him_object:
(- GET_PRONOUN_OBJ_R(2) -)
To decide which object is the her_object:
(- GET_PRONOUN_OBJ_R(3) -)
To decide which object is the them_object:
(- GET_PRONOUN_OBJ_R(4) -)
Book 2 - Scenario
Part 1 - Samares Gardens
Chapter 1 - The Gardens
Section 1 - Description
Samares Gardens is a room. "A beautiful and lush English garden in the height of summer. The hedges are neatly clipped, the borders carefully tended and the distant stately house a gothic shimmer in the midday heat.[line break][line break]A mossy stone path winds east from the lawn and down through a dense shrubbery." It is proper-named. It is plural-named. The detailed scenery is the Table of Garden Scenery.
Section 2 - Scenery
Table of Garden Scenery
topic plural description
"hedges" true "Beautifully clipped privet, including a number of baroque topiary forms."
"borders" true "In early June the borders are a riot of fragrant colour."
"grandfather's/distant/gothic/stately/house/pile" false "[Our] grandfather's stately pile."
"bright/white/sun/heat/haze" false "The bright white sun casts a shimmering haze over the garden."
"lawn/grass/sward" false "Lovingly manicured green sward. Imprinted by tiny trotter-marks."
" tiny/-- trotter/-- marks/trotter-marks" true "Hmm. That won't put the gardener in a good mood..."
Chapter 2 - Japanese Pond
Section 1 - Room
[[Japanese Pond]]
The Japanese Pond is east of the Gardens. "This is the edge of a pond in the Japanese gardens. Dragonflies flit and hover like iridescent sparks over the unruffled mirror of the water; tall bullrushes stand silently in the summer heat.[line break][line break]A mossy stone path leads west back up to the main gardens." The detailed scenery is the Table of Pond Scenery.
Section 2 - Scenery
Table of Pond Scenery
topic description plural
"tall/-- bullrushes/rushes" "Like serried ranks of green-garbed soldiers they march into the still waters." true
"glittering/-- jewels/dragonflies/flies" "Like glittering jewels, they flit, swoop and hover over the bright surface of the pond." true