"Art of Fugue" by "Victor Gijsbers, Jimmy Maher and Dorte Lassen" The story headline is "Twenty studies in counterpoint for 4 voices". The story genre is "Puzzle". Include Custom Library Messages by David Fisher. Include Editable Stored Actions by Ron Newcomb. Include Menus by Emily Short. [Include Questions by Michael Callaghan. [Clashes with Menus by Emily Short! I have taken the useful code and added it to the end of this file.]] Use MAX_STATIC_DATA of 3000000. [I might change the layout so that each turn simply produces the name of the actor + a response that no longer mentions the actor by name. This is not very important right now.] When play begins: change the library message person to third person; set the library message third person text to "[bold type][current-player][roman type]"; choose row with a Word of "Himself" in the Table of 'himself' forms; now the Word entry is "[bold type][current-player][roman type]"; choose row with a Word of "himself" in the Table of 'himself' forms; now the Word entry is "[bold type][current-player][roman type]". To say current-player: if Een is the player, say "Een"; if Twee is the player, say "Twee"; if Drie is the player, say "Drie"; if Vier is the player, say "Vier". When play begins: say "Welcome to [bold type]Art of Fugue[roman type], a collection of fiendish puzzles. Well--the first puzzles aren't too fiendish. You can change between puzzles by typing 'next puzzle' and 'previous puzzle', or restart the current puzzle by typing 'restart puzzle'. Have fun!" Chapter - Voices and the Fugue First Puzzle is a room. [We are going to create four actors. Een, Twee, Drie and Vier are the first four numbers in Dutch. Using the English names would be... problematic, to say the least.] Een is a person. The printed name of Een is "[bold type]Een[roman type]". Twee is a person. The printed name of Twee is "[bold type]Twee[roman type]". Drie is a person. The printed name of Drie is "[bold type]Drie[roman type]". Vier is a person. The printed name of Vier is "[bold type]Vier[roman type]". Een, Twee, Drie and Vier are scenery. The player is Een. [At the start of the game at least.] Count is a number that varies. Count is 0. [Count goes from 0 to 1 to 2 to 3, and is equivalent to the person who has had his turn last. (Where 4 is 0.) So if count is 0, Een is going to take the next turn.] tmpcmd is some indexed text that varies. [tmpcmd will be a very important variable, because we use it to manipulate and store the player's input. It is after all the INPUT, not the PARSED COMMAND that we want to store. "X me", for instance, is parsed to "examine Een"--and we don't want Twee, Drie and Vier to examine Een in response to "x me". We want them to examine themselves. In order to get that, we store the player's input, and reparse it when needed.] [The Table of Melodies stores the commands. We make 15 rows, for possible later use, but use only 4 or 5 now.] Table of Melodies Twee Stored Action (indexed text) Drie Stored Action (indexed text) Vier Stored Action (indexed text) "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" "wait" [15 rows] [This is the most important routine!] First every turn when not looking (this is the play and write the fugue rule): if count is 0: [New commands are stored only on Een's turn.] now tmpcmd is the player's command; [ if the again boolean is true, now tmpcmd is "again"; [See below, the section about again.]] choose row 3 in the Table of Melodies; now the Twee Stored Action entry is tmpcmd; choose row 4 in the Table of Melodies; now the Drie Stored Action entry is tmpcmd; choose row 5 in the Table of Melodies; now the Vier Stored Action entry is tmpcmd; repeat with N running from 1 to 14: [because 15 rows] [Here we push all the rows up.] choose row N in the Table of Melodies; let M be N + 1; let Q be the Twee Stored Action in row M of the Table of Melodies; now the Twee Stored Action entry is Q; [ say Q;] let Q be the Drie Stored Action in row M of the Table of Melodies; now the Drie Stored Action entry is Q; [ say Q;] let Q be the Vier Stored Action in row M of the Table of Melodies; now the Vier Stored Action entry is Q; [ say Q;] increase move counter by 1; if move counter is less than 501: [For move counter, see the chapter on keeping track of the player's solution, at the end of this file] choose row move counter in the Table of Player Solution; now the move entry is tmpcmd; now count is 1 + count; [We increase the person whose turn it is.] if count is 4, now count is 0; if count is 0, change player to Een. Rule for reading a command when count is not 0: [When count is not 0, this routine reads a command from the Table of Melodies and uses it as input.] choose row 1 in the Table of Melodies; if count is 1: change player to Twee; [We make the actor the protagonist. Otherwise, the standard library would give us insane amounts of headaches. Most actions are not reported for non-protagonists.] now tmpcmd is the Twee Stored Action entry; if count is 2: change player to Drie; now tmpcmd is the Drie Stored Action entry; if count is 3: change player to Vier; now tmpcmd is the Vier Stored Action entry; change the text of the player's command to tmpcmd. [And now Inform 7's standard parsing + running the action routines take over.] Chapter - Commands [We don't want multiple things happening in a single turn, so "all", "and", and so on are killed.] Section - All After reading a command (this is the reject all rule): now tmpcmd is the player's command in lower case; if tmpcmd matches the regular expression " all": say "(The use of 'all' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; if tmpcmd exactly matches the regular expression "^all.*": say "(The use of 'all' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; if tmpcmd exactly matches the regular expression "rules all": now tmpcmd is "rules all"; change the text of the player's command to tmpcmd. Section - And After reading a command (this is the reject and and then and dot and comma rule): now tmpcmd is the player's command in lower case; if tmpcmd matches the regular expression " and ": say "(The use of 'and' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; if tmpcmd matches the regular expression "\.": say "(The use of the dot is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; if tmpcmd matches the regular expression " then ": say "(The use of 'then' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; if tmpcmd matches the regular expression ",": say "(The use of the comma is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; change the text of the player's command to tmpcmd. Section - More all and and [The previous will still allow "all" or "and" in disambiguation questions. This code will remove even that possibility.] The magic rule is listed before the generate action rule in the turn sequence rules. This is the magic rule: let L be the multiple object list; if the number of entries in L is greater than 1: say "(Removing objects--no voice can sing more than one note at a time!)"; alter the multiple object list to {nothing}. [I think we will need to remove disambiguation completely. TODO] Section - Oops After reading a command (this is the reject oops rule): now tmpcmd is the player's command in lower case; if tmpcmd matches the regular expression "oops ": say "(The use of 'oops' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; change the text of the player's command to tmpcmd. Section - Again, g [We want again to be more interesting that it would normally be. Normally, "g" will simply copy the last input, and will not be written into the table as "again". What we want is an again that copies the last action. On the other hand, we want to limit successive agains to only 1, because all puzzles would become trivial otherwise.] [It is conceivable that we change the behaviour of again later. That would entail the rejection of puzzle 4.] [I have now simply forbidden again. and rejected puzzle 4.] [Agncmd is an indexed text that varies. The again boolean is a truth state that varies. The again boolean is false. Before reading a command (this is the prepare for again rule): now agncmd is tmpcmd; if agncmd is "", now agncmd is "wait". After reading a command (this is the reimplement again rule): now tmpcmd is the player's command in lower case; if tmpcmd exactly matches the regular expression "g" or tmpcmd exactly matches the regular expression "again": choose row 2 from Table of Melodies; if Twee Stored Action entry is "again" and count is 0: say "(Again and again? Now [bold type][the player][roman type] is simply confused.)"; now tmpcmd is "wait"; otherwise: now tmpcmd is agncmd; now the again boolean is true; change the text of the player's command to tmpcmd. Every turn: now the again boolean is false.] [See also the play and write the fugue rule above.] After reading a command (this is the reject again rule): now tmpcmd is the player's command in lower case; if tmpcmd exactly matches the regular expression "again" or tmpcmd exactly matches the regular expression "g": say "(The use of 'again' is forbidden in [italic type]The Art of Fugue[roman type]. Replacing your command with 'wait'.)"; now tmpcmd is "wait"; change the text of the player's command to tmpcmd. Section - Disambiguation [Disambiguation questions wreak havoc with our puzzles. We simply want to reject the commands when there is ambiguity.] Rule for asking which do you mean: say "You'll have to be more specific." Chapter - Actions [Lots of text replaced with text that mentions the actor. Much of this may be removed if I introduce the alternative layout mentioned at the beginning of the source.] Section - Singing A person has a number called the singing number. The singing number of a person is usually 1. Instead of an actor singing: if the singing number of the actor is: -- 1: say "[The actor] sings '[italic type]Frère Jacques, frère Jacques,[roman type]'."; -- 2: say "[The actor] sings '[italic type]Dormez-vous? Dormez-vous?[roman type]'."; -- 3: say "[The actor] sings '[italic type]Sonnez les matines! Sonnez les matines![roman type]'."; -- 4: say "[The actor] sings '[italic type]Din, dan, don. Din, dan, don.[roman type]'."; increase the singing number of the actor by 1; if the singing number of the actor is 5, now the singing number of the actor is 1. Section - Jumping Instead of an actor jumping: say "[The actor] jumps with a soft 'thump'.". Section - Waiting Instead of an actor waiting: say "[The actor] remains absolutely silent." Section - Looking Check an actor looking: if the actor is not Een, say "[The actor] looks at the surroundings." instead. Section - Examining Instead of an actor examining: say "[The actor] examines [the noun] with obvious interest.". Section - Inventory Instead of an actor taking inventory: say "[The actor] carries:[line break]"; list the contents of the actor, with newlines, indented, giving inventory information, including contents, with extra indentation. Section - Taking The can't take people's possessions rule is not listed in any rulebook. Check an actor taking (this is the new can’t take people’s possessions rule): let the local ceiling be the common ancestor of the actor with the noun; let H be the not-counting-parts holder of the noun; while H is not nothing and H is not the local ceiling: if H is a person: say "[The actor]: [=> noun][that|those] seem[-s] to belong to [H]."; stop the action; let H be the not-counting-parts holder of H. Section - Custom Library Messages Table of custom library messages (continued) Message Id Message Text LibMsg "[The actor]: Taken." LibMsg "[The actor]: Removed." LibMsg "[The actor]: Dropped." LibMsg "[The actor] [eats*] [the % dobj]. Not bad." LibMsg