-- menu.ala -- version 1.0 -- -- Alan source code example demonstrating -- a few techniques for implementing a menu -- in an Alan game. -- -- Written in Alan 2.8 (Works fine in 2.6 and 2.7) -- -- stephen.griffiths@xtra.co.nz -- February 1999 --------------------------------------------------- -- An object to hold the menu status information OBJECT menu_system HAS level 0 . HAS selection_bad "no" . END OBJECT. --------------------------------------------------- -- Normal game commands aren't disabled while the menu is on-screen -- If player selects a non-menu command - eg:'north' or 'attack troll' -- then the game will continue so this event is scheduled to run one turn -- after a menu is entered to return the game to 'not-in-menu' status. -- If the player continues to use menu commands then the event is -- cancelled and re-scheduled to run on the next turn. EVENT not_in_menu SET level OF menu_system TO 0 . SET selection_bad OF menu_system TO "no". END EVENT. --------------------------------------------------- -- Add a 'using the menu?' check to the normal quit -- command as the same command will now be used to -- quit a menu as well as quit the whole game. SYNTAX 'quit' = 'quit'. SYNONYMS q = 'quit'. VERB 'quit' DOES IF level OF menu_system > 0 THEN "Ok. Back to the game ...." SET level OF menu_system TO 0 . SET selection_bad OF menu_system TO "no" . LOOK. -- debatable whether want this 'look' or not. ELSE QUIT. END IF. END VERB 'quit'. --------------------------------------------------- -- Command to start the menu system and display the 'menu_1' object which -- contains the text for the main menu. SYNTAX menu = menu. SYNONYMS help = menu. VERB menu CHECK level OF menu_system = 0 ELSE "You are already in the menu system." DOES SET level OF menu_system TO 1. SCHEDULE not_in_menu AfTER 1. "$p$p(The purpose of this program is to provide source code which demonstrates how to program menus in 'Alan'. This program demonstrates two different menu-selection methods which may be a little confusing. Also the menus are not very well laid out, sorry, as I had trouble thinking of enough menu topics to adequately illustrate the programming techniques in the source code.)" DESCRIBE menu_1. END VERB. --------------------------------------------------- -- Menu verbs -- -- Note that the IF statements in these verbs must be customised to -- reflect the actual menu structure. -- eg: if there's no option c on the 'menu_111' menu then the author needs -- to remove the section of the IF statement in the 'c' verb that refers -- to menu_1113 -- -- Note that there's two different item-selection methods used in this -- demo - the 'a,b,c..' and 'topic n' methods. In a real game you'd only -- need one or the other system as you'd want all your menus to work in a -- consistent way for the player's convenience. SYNTAX a = a. b = b. c = c. d = d. p = p. VERB a CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF level OF menu_system = 1 THEN DESCRIBE menu_11. ELSIF level OF menu_system = 11 THEN DESCRIBE menu_111. ELSIF level OF menu_system = 111 THEN DESCRIBE menu_1111. ELSIF level OF menu_system = 112 THEN DESCRIBE menu_1121. ELSE "'a' is not a valid option." SET selection_bad OF menu_system TO "yes". END IF. -- if the player's selection was valid then -- display the 'footer' text for the new menu and update the menu -- level number otherwise do nothing except turn the 'bad' flag -- off again ready for the player's next attempt. IF selection_bad OF menu_system = "yes" THEN SET selection_bad OF menu_system TO "no". ELSE "$p(Enter P for previous menu, Q to quit menu and return to game.)" SET level OF menu_system TO (level OF menu_system * 10) + 1. END IF. END VERB a. VERB b CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF level OF menu_system = 1 THEN DESCRIBE menu_12. ELSIF level OF menu_system = 11 THEN DESCRIBE menu_112. ELSIF level OF menu_system = 111 THEN DESCRIBE menu_1112. ELSIF level OF menu_system = 112 THEN DESCRIBE menu_1122. ELSE "'b' is not a valid option." SET selection_bad OF menu_system TO "yes". END IF. IF selection_bad OF menu_system = "yes" THEN SET selection_bad OF menu_system TO "no". ELSE "$p(Enter P for previous menu, Q to quit menu and return to game.)" SET level OF menu_system TO (level OF menu_system * 10) + 2. END IF. END VERB b. VERB c CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF level OF menu_system = 111 THEN DESCRIBE menu_1113. ELSIF level OF menu_system = 112 THEN DESCRIBE menu_1123. ELSE "'c' is not a valid option." SET selection_bad OF menu_system TO "yes". END IF. IF selection_bad OF menu_system = "yes" THEN SET selection_bad OF menu_system TO "no". ELSE "$p(Enter P for previous menu, Q to quit menu and return to game.)" SET level OF menu_system TO (level OF menu_system * 10) + 2. END IF. END VERB c. VERB d CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF level OF menu_system = 111 THEN DESCRIBE menu_1114. ELSE "'d' is not a valid option." SET selection_bad OF menu_system TO "yes". END IF. IF selection_bad OF menu_system = "yes" THEN SET selection_bad OF menu_system TO "no". ELSE "$p(Enter P for previous menu, Q to quit menu and return to game.)" SET level OF menu_system TO (level OF menu_system * 10) + 2. END IF. END VERB d. VERB p CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF level OF menu_system = 1 THEN "No 'previous' menu - you are at the top level of the menu." ELSE -- "/" in Alan means 'integer division' - ie result of division -- is the whole number portion - the decimal part is thrown away -- so "/10" effectively moves the digits one place to the right -- and throws away the rightmost digit -- eg 132 /10 = 13 SET level OF menu_system TO (level OF menu_system / 10). IF level OF menu_system = 1 THEN DESCRIBE menu_1. ELSIF level OF menu_system = 11 THEN DESCRIBE menu_11. ELSIF level OF menu_system = 12 THEN DESCRIBE menu_12. ELSIF level OF menu_system = 111 THEN DESCRIBE menu_111. ELSIF level OF menu_system = 112 THEN DESCRIBE menu_112. ELSIF level OF menu_system = 123 THEN DESCRIBE menu_123. ELSIF level OF menu_system = 126 THEN DESCRIBE menu_126. ELSE "Oops, there's a problem! $nMenu" SAY level OF menu_system. "isn't a valid menu screen. $pExiting menu now - type 'menu' to re-enter the menu system at the top level." SET selection_bad OF menu_system TO "yes". END IF. IF selection_bad OF menu_system = "yes" THEN SET selection_bad OF menu_system TO "no". SET level OF menu_system TO 0. ELSE IF level OF menu_system > 1 THEN "$p(Enter P for previous menu, Q to quit menu and return to game.)" END IF. END IF. END IF. END VERB p. --------------------------------------------------- SYNTAX choose = choose (opt) WHERE opt ISA INTEGER ELSE "You must enter a number - eg: 'c 3'" SYNONYMS topic, t = choose. -- usually would use 'c' as the synonym VERB choose CHECK level OF menu_system > 0 ELSE "That command is only valid within the menu system." DOES CANCEL not_in_menu. SCHEDULE not_in_menu AfTER 1. IF opt = 1 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_121. ELSIF level OF menu_system = 123 THEN DESCRIBE menu_1231. ELSIF level OF menu_system = 126 THEN DESCRIBE menu_1261. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 2 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_122. ELSIF level OF menu_system = 123 THEN DESCRIBE menu_1232. ELSIF level OF menu_system = 126 THEN DESCRIBE menu_1262. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 3 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_123. ELSIF level OF menu_system = 123 THEN DESCRIBE menu_1233. ELSIF level OF menu_system = 126 THEN DESCRIBE menu_1263. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 4 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_124. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 5 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_125. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 6 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_126. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSIF opt = 7 THEN IF level OF menu_system = 12 THEN DESCRIBE menu_127. ELSE SET selection_bad OF menu_system TO "yes". END IF. ELSE SET selection_bad OF menu_system TO "yes". END IF. IF selection_bad OF menu_system = "yes" THEN SAY opt. "is not a valid option." SET selection_bad OF menu_system TO "no". ELSE "$p(Enter P for previous menu, Q to quit menu and return to game.)" SET level OF menu_system TO (level OF menu_system * 10) + opt. END IF. END VERB choose. --------------------------------------------------- -- menu objects -- -- These are used rather than including menu text within verbs as -- several verbs may actually display the same text - eg 'menu' and -- 'p' (for previous menu) may both display the main menu text. -- Using objects means just need 'DESCRIBE ' statements repeated -- in the relevant verbs. OBJECT menu_1 DESCRIPTION "$pMain Menu $pSelect an option:" "$p $n$tA$t-$tPlaying, & writing, I.F.$t(uses 'a,b,c' verbs) $n$tB$t-$tMiscellaneous Notes.$t(uses 'choose topic' verb) $n$tQ$t-$tQuit this menu." END OBJECT menu_1. ---- OBJECT menu_11 DESCRIPTION "$pGeneral Interactive Fiction Information $pSelect an option:" " $p$tA$t-$tCommons Commands used to play I.F. games $n$tB$t-$tWriting I.F. games with the 'Alan' system " END OBJECT menu_11. OBJECT menu_12 DESCRIPTION "$pNotes are available on the following topics:" "$pEnter 'topic n' or 't n' $nwhere 'n' is the number of your choice" " $p$t1$t-$tWhy doesn't this menu use a,b,c options. $n$t2$t-$tWhy have a 'topic' verb? $n$t3$t-$tLimitations of this menu system. $n$t4$t-$tA third item selection method. $n$t5$t-$tNon-text 'action' items. $n$t6$t-$tWho wrote this program? $n$t7$t-$tWhy? " END OBJECT menu_12. ---- OBJECT menu_111 DESCRIPTION "$pStandard Interactive Fiction Commands $pSelect an option:" " $p$tA$t-$tMoving around. $n$tB$t-$tInteracting with objects. $n$tC$t-$tInteracting with characters. $n$tD$t-$tMiscellaneous commands. " END OBJECT menu_111. OBJECT menu_112 DESCRIPTION "$pWhere to obtain the Alan I.F. Authoring System $pSelect an option:" " $p$tA$t-$tThe Alan Web Site. $n$tB$t-$tThe I.F. Archive ftp Site. $n$tC$t-$tVia Internet Email. " END OBJECT menu_112. ---- OBJECT menu_1111 DESCRIPTION "$pMoving around. $pnorth,south,southwest,etc (abbreviate as n,s,sw,etc) $nalso enter or exit in some locations $ngo north, etc also works " END OBJECT menu_1111. OBJECT menu_1112 DESCRIPTION "$pObjects $pexamine or look at 'object' (abbr. x 'object') $ntake or get 'object' $ndrop or throw 'object' $nput 'object' in (or on) 'another object' $ngive 'object' to 'character' " END OBJECT menu_1112. OBJECT menu_1113 DESCRIPTION "$pCharacters $pask 'character' about 'subject' $ntell 'character' about 'subject' $ngive 'object' to 'character' " END OBJECT menu_1113. OBJECT menu_1114 DESCRIPTION "$pGame Status $pinventory (abbr. i ) - list objects being carried $nlook (abbr. l ) - repeat description of current location $nscore - display game points currently earned $pStopping and starting game $psave - save current game state to a disk file $nrestore - restore previously saved game from disk file $nrestart - start playing game again $nquit - exit the game $pMiscellaneous $pbrief - only describe a location when first visit it $nverbose - display description each time visit a location $nwait (abbr. z ) - do nothing for a turn " END OBJECT menu_1114. ---- OBJECT menu_1121 DESCRIPTION "$pThe Alan Web Site. $ihttp://www.pp.softlab.se/thomas.nilsson/alan/ " END OBJECT menu_1121. OBJECT menu_1122 DESCRIPTION "$pThe I.F. Archive ftp Site. $iftp://ftp.gmd.de/if-archive/ $ihttp://www.if_archive.org/" END OBJECT menu_1122. OBJECT menu_1123 DESCRIPTION "$pVia Internet Email. $iSend a message containing the text SEND INFO to $i$talan-request@softlab.se" END OBJECT menu_1123. ---- OBJECT menu_121 DESCRIPTION " $iThe use of a,b,c etc for menu items runs into a problem if there's more than three items because 'd' might already be defined as a synonym for the direction 'down' and almost certainly 'e' will be short for 'east'. This menu demonstrates another way the player can specify their item choice. " END OBJECT menu_121. OBJECT menu_122 DESCRIPTION " $iYou can't use 1,2,3 etc as Alan verbs because a command can't start with a number. So you can define a command like 'choose n' abbreviated to 'c n' where n is the number of the option required. (In this demo the verb is 'topic n' coz the abbreviation 'c' is already defined as a verb for the a,b,c style of menu-selection. Of course, in a real game you wouldn't mix and match the two selection methods as this demonstration does. " END OBJECT menu_122. OBJECT menu_123 DESCRIPTION "Inherent Restrictions within this Menu System" "$pChoose a topic by entering 't n' where n is the number of your choice:" "$p$t1$t-$tNine Items per menu" "$n$t2$t-$tNine levels of menus" "$n$t3$t-$tFree Letters available for item labels" END OBJECT menu_123. OBJECT menu_124 DESCRIPTION "Third Alternative Menu Selection Method" "$n$t (Not implemented in this example program.) $pThere's no reason (except that its easier to program) why you must use one-letter verbs to select menu items. For example you could have .... $pAuthor's Notes $n$tAUTHOR$t-$tAbout the author. $n$tCREDITS$t-$tBeta-testers. $n$tALAN$t-$tAbout the authoring system used to write this game. $n$tHISTORY$t-$tFootnotes about the era this game is set in. $n$tLEGAL$t-$tCopyright notice and Disclaimer. $pWith this sort of menu you could allow the player to access the items directly during game-play as well as from a menu. You can then have the verbs keep track of whether the menu was active or not to control if the player is returned to the menu or the game after the menu item is executed." END OBJECT menu_124. OBJECT menu_125 DESCRIPTION "Note that in this demo all the menu items simply display bits of text. But they could also perform actions just as well. So you could do 'choose your own adventure' games with menus like $p$tDo you want to.... $p$t$tA$t-$tAttack Troll $n$t$tB$t-$tKiss Troll $n$t$tC$t-$tGo North $p$tThe 'a' verb would then have in its statement something like... $iELSIF level OF menu_system = 14 THEN $i$t""You kill the troll with your trusty sword. Now you can $i$tfinally cross the eastern bridge."" $i$tLOCATE hero AT eastern_kingdom. $i$tSCORE 5." END OBJECT menu_125. OBJECT menu_126 DESCRIPTION "Who wrote this demo?" "$pChoose a topic by entering 't n' where n is the number of your choice:" "$p$t1$t-$tAuthor email address" "$n$t2$t-$tFeedback requested" "$n$t3$t-$tWhy is this info split up into three submenus?" END OBJECT menu_126. OBJECT menu_127 DESCRIPTION "I wrote this program because I hoped that other Alan programmers would find it useful. You're welcome to use this code as a basis for your own menus. I hope you'll share any improvements and new ideas for the benefit of the Alan programming 'community.'" END OBJECT menu_127. ---- OBJECT menu_1231 DESCRIPTION "$pNine Items per menu $pThis limitation is because of the menu level numbering scheme within the program. Each menu screen seen by the player is a separate Alan object identified by an id number. The first menu is called menu_1. Menu screens off that are called menu_1x (where x can be 1 to 9). The menu screens off each one of those screens are labelled menu_1xx. $pmenu_1 ----> menu_11 --> menu_111 $n$t$t$t$t$t$t menu_112 $n$t$t$t$t$t$t etc $n$t$t$t menu_12 --> menu_121 $n$t$t$t$t$t$t menu_122 $n$t$t$t$t$t$t etc $n$t$t$t$t : $n$t$t$t$t : $n$t$t$t menu_18 $n$t$t$t menu_19" "$pTake menu_12 as an example. Menu_12 is the second menu off the main menu. (The player selects if off the main menu by entering 'b' or 't 2' or whatever other verb you might program to do it.) Menu_12 could have up to nine submenus off it which would be labelled menu_121, menu_122, menu_123, ... , menu_129. A tenth menu off menu_12 would have to be called menu_130 or something. That wouldn't work coz the program would see the '13' bit and relate it to the _third_ submenu off the main menu not the second one. Or you could try menu_1210 but that wouldn't work either because that would signify (if you could had a menu 0 under this naming scheme) the zero'th menu off the first submenu off the second submenu off the main menu! :-)" END OBJECT menu_1231. OBJECT menu_1232 DESCRIPTION "$pNine Levels of menus $pWell about nine levels. I haven't worked it out exactly but it looks like the largest number you can have in Alan is measured in the billions so you could perhaps have a menu_1999999999. Hopefully you'd never need to go nine menu levels deep anyway. That'd be pretty confusing for the player. As would having nine options on one menu. So hopefully these limitations won't be a problem in practice." END OBJECT menu_1232. OBJECT menu_1233 DESCRIPTION "$pFree Letters available for item labels $pWith the 'a,b,c...' method of selection you're further limited to the number of letters you can think of that aren't used for other player verbs or exits. (d,e,g,i,l,n,p,q,s,u,x,z are standard abbreviations traditionally defined for something.) $pBut you could use two letter commands or whatever (see menu item 'A third menu selection alternative' for an example.) " END OBJECT menu_1233. ---- OBJECT menu_1261 DESCRIPTION "$pThis program was written by Stephen Griffiths. Email address is sg@xtra.co.nz" END OBJECT menu_1261. OBJECT menu_1262 DESCRIPTION "$pI would really welcome feedback on this demo program. Let me know if you find it useful, discover bugs, have a better way of doing menus or whatever. I look forward to hearing from other users of 'Alan'" END OBJECT menu_1262. OBJECT menu_1263 DESCRIPTION "$pYes I know all these dinky little submenus are annoying but I needed to have at least two submenus off the 'topic n' submenu to make the choose/topic verb example in the source more informative." END OBJECT menu_1263. --------------------------------------------------- -- A dummy location to have somewhere to start this demo game LOCATION somewhere NAME somewhere 'in' a hypothetical game DESCRIPTION "$iYou are in a room dimly lit only by the full moon shining through a small window high on the eastern wall. A thick swirling mist several inches thick cloaks the floor. Many fascinating objects and items of furniture festooned with cobwebs fill the room. $iWell, no, not really! Actually this location is empty and exists for no reason other than to have a place to start from in this demonstration." EXIT north,south,east,west TO somewhere CHECK "You can't go anywhere. You can only look at the menu or quit, sorry." END EXIT. END LOCATION. START AT somewhere. "----------------------------------------------------------------------" "$pMenu demonstration" "$n------------------" "$pAn Alan IF System coding example$iBy Stephen Griffiths" "$p Player Commands available in this 'game': $n$tmenu$t$t$t-$tsee the demonstration $n$tnorth,east etc$t-$tjust there so you've got some non-menu commands $n$tquit$t$t$t-$texit the program" "$p----------------------------------------------------------------------"