In an old i6 thread, I see that someone was having trouble getting a start menu to work correctly, and zarf made a suggestion to launch the start menu during the first look action.
I’m using I7, but still wondering if there’s anything I need to be cautious of in trying to implement a start menu. Ideally I’d like to use the menu I already have (built with Wade Clarke’s Menus extension) so that the same menu can be accessed either before or during the game.
The Menus extension uses an activity to display the menu.
Are activities allowed to run “when play begins,” before the first turn? Even if I can get this to seemingly work, is it not a good idea? Should I launch the menu during the look action just to be on the safe side (assuming I can get that to work correctly)?
(So far I can get the menu to show up, but one of the options I added–to start the game–isn’t working right. It seems to be waiting for an enter after the keypress for some reason, even though the other options don’t.)
You can run activities whenever you like! Whenever you print the name of a thing, for example, that runs an activity. So you can absolutely put a menu in a “When play begins:” rule before the game properly starts.
If going that route, I think you might want to use a “Last when play begins” rule, to make sure your menu activity runs after any other “when play begins” rules. Even if your game doesn’t do any sort of setup there, you might be using an extension that does, which may or may not cause unwanted side effects.
An activity is really just a rulebook with “before” and “after” hooks stuck onto it. Whether the standard library uses a rulebook or an activity comes down to the likelihood that anyone will need those hooks. “Reading a command” is an activity because you might want to mess with the text “after reading a command”, or show a tutorial “before reading a command”; “printing the name of something” is an activity so you can stick adjectives on before and (being worn) on after; and so on.
“When play begins” and “visibility”, on the other hand, are just rulebooks, because it doesn’t really make sense to stick things before or after them: “when play begins” doesn’t accomplish a specific task that you’d want to hook into before/after (it does a whole bunch of unrelated things depending what the story needs), while “visibility” accomplishes a specific task but it’s not really one the player sees.
So activities get called all over the place. I suspect the reason Emily Short made menus an activity is so they can set up the screen “before” and reset it “after”, with the menu itself being in the middle. (Unfortunately, I can’t seem to find the extension itself in any of the repositories to confirm this.)
(If you’re using my “before processing a command” extension, that’s actually just a rulebook with a misleading name. There’s no “for processing a command” or “after processing a command” rules, only “before”, since that’s the only hook that really makes sense logistically.)
Are you firing off the menus with carry out the displaying activity or try asking for help? Asking for help performs the looking action after the activity completes, which might make things weird.
If you share the rule you’re using to start the game, I can look at it (since I use Wade’s extensions).
I have multiple “When play begins rules.” Some are just setting variables and things. But the main one is a list of tasks, and in the midst of trying to add this start menu, I divided that list into two rules, so that the menu variables could be set in the first rule (a regular “When Play Begins” rule), and the menu could be displayed in the second rule (a “Last when play begins” rule.) I think there was a “Last when play begins” rule in the Menus extension itself that I needed to account for.
My “Last when play begins rule” looks like this:
Last when play begins (This is the show the start menu and then the story intro rule):
carry out the displaying activity;
clear the screen;
Cue Story Intro.
(“Cue Story Intro” is a phrase that prints paragraph breaks and text, then has a “wait for any key,” and then puts some things in the status line.)
I’m wondering if the problem is the way I’ve tried to add the action in the table. That row looks like this:
Table of Help Contents
title (text) subtable (table name) description (text) toggle (rule) used (number) bookpage (number) localpage (number)
"Start the Game" -- -- menuquit rule
I also tried the “menuabort rule.” Both of those rules are in the Menus extension. But I don’t understand what the rules do exactly.
There’s some logic in the menuquit rule that I don’t fully understand. My guess is that selecting the option means that the menu is not at the “top” level. Doing something like this works better. As an example, I know it’s not the goal.
mn_master_table is table of demo contents.
table of demo contents
title (text) subtable (table name) description (text) toggle (rule) used (number) bookpage (number) localpage (number)
"Go down a level" table of descent -- -- -- -- --
table of descent
title (text) subtable (table name) description (text) toggle (rule) used (number) bookpage (number) localpage (number)
"return" -- -- menuquit rule -- -- --
This is a good question for @severedhand, I’m sure/I hope it’s only a matter of knowing what the rule is looking for.
Found the issue. The menus don’t account for the toggle rule potentially exiting the menu system.
Include Basic Help Menu by Wade Clarke.
To show menu contents:
if mn_action is 2: [IE if player re-enters menu system having exited from localmode..]
now mn_action is 0;
follow the menuprint rule;
if mn_action is 2: [IE player wants to exit menus immediately]
rule succeeds;
otherwise:
mn_clear hint flags;
unless mn_phase is 3:
now mn_phase is 1;
while mn_menupresent is true:
let __index be 0;
while __index is not 1:
let globaljump be false; [a temp flag for use during the drill down sequence]
now mn_breadcrumb is the path corresponding to a storer of current menu in table of pagey menus;
if mn_refresh is true:
reprint current menu;
now mn_refresh is true;
now mn_action is 0;
let __x be 0;
let F be 0;
if mn_phase is 3: [If we're drilling down..]
repeat with N running from 1 to number of rows in current menu:
choose row N in current menu;
if there is a toggle entry or used entry is not 0: ['toggle' clause checks for toggle entries, 'used' clause checks for hint pages]
if there is a toggle entry:
now F is localpage entry; [Retrieve number of nearest global page (which was stored here during startup scan)]
otherwise:
now F is used entry; [Retrieve number of nearest global page (which was stored here during startup scan)]
if F < 0:
now F is 0 minus F; [Positive-ise choice]
if F is 0: [This could happen if the toggle/hint entry occurs at the highest menu level and before any non-toggle entries]
now F is 1; [If it does, point to global page 1 instead]
now mn_currentbookpage is F;
now globaljump is true; [This signals that F contains a global page #]
break;
otherwise: [If no toggle entry, we will choose this row. Whether it has text content or leads to another subtable, we choose it]
now F is N; [Mark current row as the one we will choose]
break;
if globaljump is false:
if F is listed in mn_temp_list: [It SHOULD be!]
repeat with L running from 1 to number of entries in mn_temp_list:
if entry L in mn_temp_list is F:
now F is L;
break;
now current menu selection is F;
otherwise:
now __x is the chosen letter;
if globaljump is false:
if __x is a number listed in the Table of Menu Commands: [If the drill down set the value of current menu selection, __x will still be 0.]
follow the effect entry;
if mn_menupresent is false:
now __index is 1;
otherwise:
if __x is a number listed in the Table of Extra Menu Choices:
now current menu selection is choice entry;
otherwise if F is 0: [F will be non-0 if we're drilling down and have already calculated the value of current menu selection for this round.]
now current menu selection is __x minus 48;
if current menu selection < 1 or current menu selection > mn_temp_counter:
now __index is 1; [If keypress was not a valid menu choice, rerun this loop-]
now mn_refresh is false; [-but without reprinting the menu]
otherwise:
now mn_temp_selection is entry current menu selection of mn_temp_list;
choose row mn_temp_selection in the current menu;
unless there is a toggle entry:
now mn_current_menu_title is title entry;
if there is a toggle entry:
follow toggle entry;
if mn_menupresent is false:
now __index is 1;
otherwise if there is a subtable entry and subtable entry is not table of hinting:
now the current menu is subtable entry;
increment mn_stackpointer;
choose a blank row in table of mn_stack;
now desk entry is current menu;
now __index is 1;
otherwise:
now mn_phase is 2; [Trigger move to localmode]
if mn_phase is 2:
mn_count the local pages; [Puts the number of pages in the current local topic into mn_temppagecount]
otherwise if mn_phase is 3 and globaljump is true:
mn_identify the book page; [Sets current menu, mn_current_menu_title, mn_temp_selection, and does a mn_count the local pages for the target global page]
now mn_phase is 2;
if mn_phase is 2:
now mn_localmode is true;
follow the menuprint rule;
if mn_action is 2: [IE player wants to exit menus immediately]
now __index is 1;
otherwise:
mn_clear hint flags;
now mn_phase is 1.
Table of Testing
title (text) subtable (table name) description (text) toggle (rule) used (number) bookpage (number) localpage (number)
"Start Game" -- -- menuabort rule
"Introduction to [story title]" -- "Welcome to [story title]."
"Instructions for Play" table of instruction options --
When play begins:
now mn_master_table is Table of Testing;
Last when play begins:
carry out the displaying activity;
clear the screen;
The Garden is a room.
Basically, what I had to do was recreate the “to show menu contents” to make a quick assessment of mn_menupresent after the toggle entry so that I could switch the __index flag.
if there is a toggle entry:
follow toggle entry;
if mn_menupresent is false:
now __index is 1;
That got it to work; it was just a flag not being set at the right time if you weren’t accessing the rules from their assigned keys.
Thankfully this is roughly what I had to do for Emily Short’s extension so I knew it would be an __index problem.
EDIT: Whoops! Sorry, didn’t include the bottom parts by accident. Thought I did. Put my testing table and a starting room back in there, now.
(Basic Help Menu itself has a line to include Menus, I just used the last among the string of extensions while trying to test this. Hence why the change still works!)
Well, starting the virtual machine is an activity, so the general activity mechanism must clearly work well before when play begins. (The rulebook machinery too, since starting the virtual machine is called by the startup rules.) So, I think it should be okay for the most part?
“Starting the virtual machine” is a nuisance because you shouldn’t print anything in that activity. (I think I saw some workaround for this in the next Inform, but it’s hacky and best avoided.)
“When play begins” is totally fine. Everything’s prepped at that point.