Description of File Format used by wizard in Audio Adventure Engine. +++ This is all the stuff you'll never need to know if you just wait for the wizard to come out. The wizard will talk with you in plain English and take notes in the following format, which is also pretty simple. In fact you might start writing your game based upon what you'll find below (or at least the easiest parts of it) long before the wizard comes out. + Step by Step This document starts with the simple stuff and moves on to more and more advanced features. Even the most advanced features happen in a language very close to plain English. If you only use the most simple stuff from the beginning of this guide, you can still write an entertaining choice based game. As you gain experience you can try out just one slightly more advanced concept at a time, until you've mastered it all without really trying. +++ A quick word about Word wrap: Many text editors and email clients mess up lines by chopping them in half with word wrap. The Engine is forgiving of word wrap problems by adding each new line to the end of the previous line. There are certain words found only at the start of a new line. In those cases the Engine starts a new line. You can also force a new line by putting an empty line in between (using two carriage returns in a row), but that is rarely needed. +++ A quick notice about naming files: The Engine can Save Functions and Variables as files. If you have a variable by the same name as a function, normally that would cause a problem, since both would be trying to save as the same file name. The Engine will avoid such problems by adding a little something to the start of every file name. A function "WalkAbout" would be saved as "Function_WalkAbout.txt". Even though the real file name on your hard drive is called "Function_WalkAbout.txt", you can load it by just putting: LoadFunction WalkAbout So although you can load and save them by their simple names, you will find on your hard drive that: Situation FileNames start with "Situation_". Function FileNames start with "Function_". Variable FileNames start with "Variable_". (This is important to know when you write your own Game files using a text editor.) Here is the format: (Please download the posted version of this fairly often for the latest capabilities.) Each game has its own directory. The game directory has a number of files in it called situation files. One thing you can do is to let every scene in your game have its own situation file. Situation files have .txt as an extension, making them viewable in notepad. The first Situation file is always called GameFile_Start.txt. When the Game engine is told to start, it looks for this file and starts the game playing. A situation file can have any number of situations. But try not to pack more than 30 into a file so things will keep running quickly. Each file has a name, and each situation within a file has a name. You might want to have a file called AtTheMainHouse. The first situation in that file might be called KnockingAtTheFrontDoor. ++ Format for Situation Following is the format to write situations. I have put many of my explanations inside of parentheses, for clarity. Every situation in a file starts with a tilda immediately followed by the word Situation. The number of non English things like that you might be able to count on one hand (while holding a pencil). At the very least, whenever you look at the source code for a game, you will be able to easily understand what is going on and how the game works as it is written. -------------------------------------------------------- ~Situation Name: Location: (This is required. It is your name for where this moment is being played. If you can talk to someone from where you are, they are in the same location.) Example: Location: Downstairs Setting: (This is a text describing the location. It is optional but very highly advised. Whenever any character Observes, this setting will be read out loud, along with a list of any People and Things that are visible presently at the location. The setting that the Engine learns for a given location will hold true until it learns a new setting description text for that location. By changing the setting text of a location you can keep up with changes that gameplay make to the surroundings.) MapAddress: (This is optional, but recommended. The MapAddress that the Engine learns for a given location will hold true until it learns a new MapAddress for that location. The MapAddress is given as X,Y,Z. That is, EastWest, NorthSouth, Altitude, AboveBelow. At every location, the ground has a certain altitude. That gets added to AboveBelow to determine the location's absolute altitude. You can specify each of these coordinates in Miles, Feet or both. Here is an example of the format for MapAddress. MapAddress: EastWest: -20miles;-70feet (This is west of absolute zero) NorthSouth: 30miles;4feet (This is north of absolute zero) Altitude: 150feet (altitude of ground is 150 above sea level) AboveBelow: - 40feet (the location is 40 feet underground) EndMapAddress Once you have finished creating the MapAddress for the current location, you can refer to the different portions of the MapAddress as properties of the location. Example: Set HomeLocation EastWest: HomeLocation's_EastWest + 15 feet (There is more further down about properties, where this syntax is easily shown.) Access: LocationName (Adds the specified location to the list of where you can directly go to from here.) Access NOT: LocationName (Removes such location from the access list.) (When a door is open or shut you can add or remove access for both adjoining rooms.) (If other location doesn't reciprocate, access is one way, like falling into a well.) Wave: (This is optional, but if you use it, it should be the name of a wave file, without the ".wav" If you follow the name of the wave file with the word "Loop", the sound repeats until stopped or until a new function or situation is reached.) (There is also an EndlessLoop option which you would always have to stop.) (Wave sounds can now be layered. Please find at the bottom of this document.) Description: Description of Wave Sound mentioned just above. (Please find section on picture and wave descriptions.) Perform AudioSequence: (This will play an AudioSequence. If you follow the AudioSequence's name with the word "Loop", the sequence will repeat until a new AudioSequence or new situation is reached. Creating an AudioSequence is covered at the bottom of this document.) Picture: (You don't have to put anything, but if you do it should be the name of a bitmap file, without the ".bmp" If you use a bitmap file you also have to provide a unique file that describes it or your picture won't load. The description file will be the file name as your bitmap file, but end in .txt rather than .bmp. If the text file is missing or contains the same material as the one previous viewed, it will not display.) Description: Description of picture mentioned just above. (Please find section on picture and wave descriptions below.) Voice: (Options are: Mary, Mike, Sam. It defaults to Mary) Text: (This is where you write what is told the player when they enter this situiation.) StartLongText Text: This is a text command as many lines. This second line is heard right after the first line above. It is as if all the lines are run together into one big line. This all ends when the next command is given... EndLongText Voice: (If you want, you can first say something in one voice, then something in another.) Text: (You can have as many or as few of these text lines as you want.) Text: (You can have as many or as few of these text lines as you want.) ClarkKent: Hello, my friend. (Any word (other than a reserved word) when followed by a colon, will be understood as a character's name, and the phrase following it will be spoken. This example with ClarkKent would be spoken in the following manner. First you hear the narrator's voice, saying "ClarkKent says". Then you hear the closest voice available to the one described earlier for ClarkKent, and it says: "hello, my friend". This format is similar to that of a play. The place where you would describe a voice is in an equation. (find equations below). Once the word "Choice:" is encountered, the text part of a situation is done. Up until that point, when you specify a voice that is talking, it will keep being the voice talking until a different voice is specified. If you don't use a named voice, but instead just say "Text:", it will be whatever voice you named in "Voice:". That way you can finish up with narration at the end of a character's speech, if you want. (ClarkKent:) Hello, my friend. (By placing the character's name in a parentheses, you can prevent the narrator from saying: "ClarkKent says". Hint: Here is where you place any text you want the player to get when they want help. (Hot Key for Hint is F12. Whenever the player hits F12 they get the hint.) Choice: (Options are: Letter, Key, Words, YesNo, Variable, Action) (The entire Choice Structure is optional. If you omit it, you must have a single Goto File and Goto Situation where you will go at the end of your situation.) (If the Choice is YesNo, the player is expected to type Yes, No or Cancel. If the Choice is Words, the player is expected to type anything. If the Choice is Letter, the player is expected to type a letter. If the Choice is Key, the player is expected to hit a key. If the Choice is Action, the player is expected to type most of a sentence. I will talk more about Choice Action and the way that you use it later below. If the Choice is Variable, the player does not get a chance to type anything at all. Instead, the game makes a decision by itself. In this case the engine makes a decision based upon the current value of whatever variable is used. A variable is an information holder. You can have it contain a number, a word or anything someone may type. You can change the value of a variable by using equations. I'll talk more about equations later in this paper. After the Choice line comes a bunch of When parts. Each When part starts with a When line. A when line has the word "When", followed by the when condition. Whenever the Variable, or what the player types, matches the when condition, that when line comes true. If a when line comes true, the stuff right below the when line gets performed. (Here are some examples of When Parts:) When 1 Equation: ^Stamina = ^Stamina - ^Workout (You can put an Equation anywhere.) Text: The door opens, and you hear a group of frogs saying Come in. Text: You hear the sound of bagpipes and chainsaws. GotoFile: Same GotoSituation: InFrontOfOpenDoor When 2 Text: The entire house disappears, and is replaced by a mini mall.. Text: There is the scent of fresh paint. GotoFile: AtMiniMall GotoSituation: OrderingEsspresso When > 8 (This obviously has to do with numeric input) Text: Ok now, is the extra dimension behind door number 1, 2 or 3?. GotoFile: Enchanted Game Show GotoSituation: LighningBugRound When Contains "Torch" (if the Choice item contains the specified text) Text: Do you want any matches? GotoSituation: GottaLight (without a GotoFilefile, the same file is assumed!) When Contains Torch ~and Light (if the Choice item contains both specified texts) Text: Do you want any matches? GotoSituation: GottaLight (without a GotoFilefile, the same file is assumed!) When Contains Torch ~or Light (if the Choice item contains either specified text) Text: Do you want any matches? GotoSituation: GottaLight (without a GotoFilefile, the same file is assumed!) When Contains Torch ~or Light ~and put out ~or extinguish (This engine figures out the ~or stuff first, then the ~and stuff, simply because that is what's most often needed.) Text: Do you want any matches? GotoSituation: GottaLight (without a GotoFilefile, the same file is assumed!) When Else Text: That is not a valid Input, please try again. GotoFile: Same GotoSituation: Same (And after the last When part, you end the whole choice thing.) End Choice ------------------------------------------ And that, folks, is how simple it is to make up a situation. As you have probably guessed, the When lines for a YesNo are: When Yes, When No and When Cancel. In a Choice Variable the When lines can be anything you want. + Choice Letter and Choice Key Choice Letter waits a limited amount of time for the player to hit a letter. Choice Key waits a limited amount of time for the player to hit a key. Example: Choice Letter 10 (waits ten seconds for player to type a letter) Choice Key 12 (waits twelve seconds for player to hit a key) + RepeatChoice In a when line, if you want to repeat the same choice without having to go through the whole situation again, you can simply put: RepeatChoice and the engine will go directly to the top of that choice to try it again. + LetSpeak Suppose you want to deliver some instruction or prompt first, then do something else that might generate speech? If you use the LetSpeak command, the Engine will wait until either the present speech being delivered can finish getting spoken or until the player hits any key, whichever comes first. (It could be any key, even the shift key). ++ No GotoFile reached Suppose this situation ends and we never reached any goto? Then it tries to resume where it left off in the previous situation. That allows you to have a situation load a bunch of library stuff, all in a row. Yeah, but what if there's no gotos left in the previous situation either? Then it saves the game from the start of this situation and quits. (Then it would ask you to send the saved game to the author so he can fix his game.) ++ WildCards: In a Choice Variable or a Choice Words, you can use phrases that have wild cards. The asterisk (shift and 8) is used to signify a wild card. You can use wild cards anywhere in a When condition. If you have three asterisks in a row without any spaces, that stands for any number of words. If you have one or more asterisks with spaces in between, each asterisk stands for one word. Wild cards can only be used in When lines. Here are some examples of some When lines using wild cards, and what it takes for those When lines to come true: When * ignites * (any word, followed by the word ignites, followed by any word) When *** ignites (any number of words, ending with the word ignites) When * tree *** flowers (the word tree, followed by either nothing or any phrase, followed by the word flowers) When *** (this will take anything, including nothing) When * (the answer has to be just one word, any word) When *** * (the answer has to be at least one word) When *** * ignites (the answer has to be at least one word, followed by the word ignites) ++ Variables: A variable starts with a ^(carat sign). (You make a carat sign by holding the shift key and typing a 6.) Any word in your situation file that starts with a carat sign is a variable, and it stands for a place that can hold any number, word or phrase. I'll soon tell you more that you can do with variables. (The first time you use a variable it will create itself.) ++ WildCard Variables: In a Choice Words, you can pack a variable with something the player types in. You do this by using a WildCard variable. You write a wildcard variable just the same as the normal version of that variable, but you preceed the variable's carat sign with either one or three asterisks. The wild card rules stated above apply to wild card variables. One asterisk stands for one word. Three asterisks stands for a whole phrase. Here are some examples of some When lines using wild card variables, and what it takes for those When lines to come true, as well as what the value of the variable is depending on what the player types in: When Light my *^WhatIsLit (and if the player types in the phrase Light my hair, the variable is filled with the word hair.) When ***^WhatIsLit ignites (and if the player types in the phrase The house ignites, the variable is filled with the phrase The house.) +++ TypingInput WildCard Variables might be useful for doing certain things, but don't you think there ought to be an easier way to grab something that the game player types? I mean, really! How about this: TypingInput into ^A Yup, that simple. Here's an example of it in action: Text: What is your name? TypingInput into ^A (The player types Joe" and hits the Enter key). Equation: ^Output = Hello ^A & . Text: ^Output (The voice says: "Hello Joe.") ++ Choice Variables: You make a choice variable just like a Choice Words, but instead of saying Choice Words at the top of it you say Choice Variable, followed by the name of the variable you are using. When that situation is performed, then instead of waiting for the player to type something in, it reacts immediately to the present contents of the variable used. The contents of the variable used is compared to the When conditions of all the When lines just as if the contents of the variable had just been typed. What is the purpose of having the game play itself in this way?, you may ask. Fair question. Here is what they are good for: Choice Variables allow you to create games that play different every time. You can do this by carefully using Equations, and passing the results to your Choice Variable, which will send the player off in different directions based upon the result of the mathematical interaction of whatever variables you want to make up. Here are some examples of variables you can use ^Stamina, ^Workout, ^DinnerEnergy, ^SpellDifficulty, ^Distance, ^MapAdX, ^MapAdY. The sky is the limit. Of course, you don't have to use variables and equations. You can still make a very good game based simply upon user choices. But if you feel up to it, you can create a framework that can calculate all sorts of details about the game, and route the player accordingly. In order to do that, you need to know how to use Equations. ++ Equations: To make an equation, you type Equation: and then the equation, like this: Equation: ^A = ^B + ^C + Equations without using the word Equation: You don't have to use the word "Equation:". If the first thing on the line (other than spaces) is a variable, followed by an equal sign, the word Equation will be assumed. To get away with that, you have to start the line right before the variable. You can do that by putting a blank line in between. Here are some examples: ^MyVariable = Hello (This is a variable) ^^MyTempVariable = Hello (This is a temporary variable) MyFunction#3 = Hello (This is a function line used as a variable) Joe's_Stamina = 50 (This is a property used as a variable) Equations can contain two general kinds of operations: numeric and text. To a certain extent you can mix the two. When evaluating an expression, the engine will start by potecting everything inside of quotation marks. Then it will divide things up according to any parentheses you may have, and then simplify any numeric portions, and finally, do any text operations and combine the result into a number or text, depending upon what you did. + Numeric Operations: A numeric operation can be built of variables, plus signs, minus signs, asterisks, forward slashes and parentheses. Numeric operations will be performed as you would expect. The asterisk measn multiply, the slash means divide, the times and divide happen before the plus and minus, and stuff inside parentheses gets figured out before the answer to that is combined with the suff outside of the parentheses. This is just the way numeric equations show up in books. I have added a couple of higher operations for those who might wish to use them. Here are some examples of numberic operations: 6 + 3 (produces 9) 6 - 3 (produces 3) 6 * 3 (produces 18) 6 / 3 (produces 2) + Higher Math Functions: Please look at the very bottom of this document to find all those things that only you would be interested in. + Text Operations: There are also text operations. These are in a special form of plain English. If you do programming you may have other names for these operations. But we'll use plain English here so everyone can understand your game files. Text operations allow you to manipulate pieces of sentences and make up other sentences, or to look at the sentences a player types in and make decisions based upon various pieces from them. Here are the kinds of text operations. + Where ^A is within ^B after ^C: Suppose you have two variables that are each holding some text. One variable mightcontain the phrase Every good boy deserves favor. Another variable might contain the phrase good boy. You can look to find out where good boy is found inside of the whole phrase Every good boy deserves favor. Let's set that up. Let's fill the variable ^OneText with the two word phrase, good boy. Let's fill the variable ^AnotherText with the whole phrase Every good boy deserves favor. Now run the following equation: Equation: ^Position = Where ^OneText is within ^AnotherText As a result, the variable ^Position will be filled with the number 7, because the phrase "good boy" can be found starting with position 7 inside the phrase "Every good boy deserves favor". + after As you can find, I used the words: where, is, and within, but not the word after. The word after is optional. When you follow the word after with a number, the search will begin right after the position you say. There is a useful variation on how to use the word after. Instead of writing the word after, followed by a number (or variable holding a number), you can write after, followed by anyword or phrase. That way it will start its search after whatever word or phrase you say,as long as that word or phrase is found in the text that you are searching. If the word or phrase following the word after is not found within the text you are searching, then the search is done and it won't bother trying to find what comes after the word after. Therefore, when you say: Equation: ^Position = Where "box" is within "box in a box", after 1 then ^Position becomes filled with the number 10. (If you know Basic, be careful cause it starts after, not on the number you provide.) And when you say: Equation: ^Position = Where box is within box in a box, after in a then ^Position becomes filled with the number 10. + quotes not always needed, but they can keep you out of trouble You notice that the second time I did not use quotes. You can add quotes to make your game source more readable and easy to understand, but the engine doesn't always need them, and in many cases, doesn't pay any attention to them. But suppose your main character says "I never did put 2 + 2 together and figure that out." In this case, you don't want the portion "2 + 2" to be reduced to "4". As a rule of thumb, it's better to surround all text in quotes so it is clear what you're trying to do, especially when you are making equations. + ^A long of ^B at ^C This grabs a piece of whatever is in ^B. The piece is ^A spaces long, and starts at position ^C. Equation: ^Z = 3 long of "whatever" at 3 makes ^Z equal to "ate". + Left ^A of ^B This grabs the left hand portion of ^B. The piece is ^A spaces long. Equation: ^Z = Left 3 0f "witch" sets ^Z equal to "wit" + Right ^A of ^B This grabs the right hand portion of ^B. The piece is ^A spaces long. Equation: ^Z = Right 4 of "witch" sets ^Z equal to "itch" + ^A with ^B instead of ^C This makes a copy of ^A, but on the way it finds anything matching ^C and replaces it with ^B Equation: ^Z = "I am not happy" with "very" instead of "not" sets ^Z to "I am very happy". + ^A & ^B This glues the text from ^B onto the end of the text from ^A. Equation: ^Z = "sit" & "e" sets ^Z to "site" + ^A ^B And finally, a strange concept, plain text variables next to each other with no punctuation: Equation: ^Z = "when" "are" "you" "going" fills ^Z with "when are you going" Notice that without the & sign joining them the engine places a space between each text. + System Variables ^PlayingTime (This is how long the playing session has been going, in seconds.) ^Random (This is a random number from 0 to 99, different every time you grab it.) ++ Comments, Remarks You can place an appostrophe followed by the word REM at the beginning of any line. That line will be ignored by the engine, allowing you to put good documentation into your source code. Here is what it looks like: 'REM This line will be ignored, but you can read it. ++ Debug ^X This command on any line will cause the engine to serve up a prompt that says: "The value of ^X is..." (and of course the value of ^X.) This allows you to test portions of your code, then when you are satisfied you can comment out those lines by placing 'REM at the beginning of them, as shown above. This works with any variable. ++ Functions Functions are memorized scripts that you can perform at any time you call them. Here is how to create a function: + Create Function FunctionName Put any series of equations and commands in here that you want. There are many things you can put in a function. (Look toward the end for a fuller description of the imilarities and differences of functions.) In your function you can let equations make reference to any variables you want. If you want to pass some value into a function, create a variable, pack it with the value and then let some equation in your function go look at it. It's that simple. (Some would call it a sub, not a function, but I'm calling it a function because it performs a useful function, while a sub is a long sandwitch filled with deli meat.) Suppose you want to pack some starting values for some kind of generic function. You can make up any variable names you want, so you might want to include in those variable names the name of the function that likes to go look at them: Example: Equation: ^MyFunk_A = 1 Equation: ^MyFunk_B = 2 Equation: ^MyFunk_C = 3 Create Function MyFunk Equation: ^MyFunc_D = ^MyFunc_A + ^MyFunc_B + ^MyFunc_C End Function PerformFunction MyFunk Debug ^MyFunk_D This will tell you that the result is equal to 6. + Temporary Variables There is a special kind of Variable called a Temporary Variable. You can use them like evaporating scratch paper. If you create some Temporary Variables during a GameFile or Function, whenever that GameFile or Function ends, those Temporary Variables evaporate and they are forgotten, gone forever. + StartLoop All the game code lines between StartLoop and RepeatUntil will be repeated. It won't quit until the RepeatUntil stuff gets satisfied. Here is the RepeatUntil stuff, and how to satisfy it: RepeatUntil ^Variable = Value Here is an example of this stuff in action: StartLoop Text: Are we there yet? ^Counter = ^Counter + 1 RepeatUntil ^Counter = 25 The result is like Bart saying "Are we there yet?" 25 times in a row! On the grander scale, there is already the ability to do branching and looping just by the choices and Gotos. But this allows for there to be some tight real- time stuff done within a single function. You can also have loops inside loops. + End Function At the end of every function you create, you have to put "End Function". Otherwise, the engine will think that everything else in your file is part of that function! + Here is how to perform a function: Perform Function FunctionName The only restriction about functions is that they have to be created before they can be performed. Your game might start with creating a bunch of functions that will be used later throughout the game. If you want, your first situation in the game can be the first one in a chain of situations that just sets everything up for the remainder of the game. Each situation in the chain of them can have the creation of many People, Things, Verbs, Powers, Variables and Functions. The last situation in the setup chain will finally point to a situation that has a Choice in it. That would be the first real situation of game play. Even the first few choices might be used to simply enter the player's name and gather some information to help set up and tailor the game for their use. You can structure it however you want. ++ Real Time game play You can make real time games by using Choice Variables and WaitForKey. The Choice Variable has been covered. The WaitForKey can be used to get input from the person playing the game. + WaitForKey Time This command Waits the specified number of seconds for a key. This lets you use Shift, Ctrl or Alt as separate keys. (If your only interest in those three keys is in how they modify other keys, use WaitForLetter). When you hit a key it sets five System Variables: ^Key (The key that was hit.) ^Shift (1 or 0; 1 if Shift was held during the key press.) ^Ctrl (1 or 0; 1 if Ctrl was held during the key press.) ^Alt (1 or 0; 1 if Alt was held during the key press.) ^ResponseTime (This is how long WaitForKey waited until the user responded.) The Time can be a variable that stands for the number of seconds. It is rounded off to the nearest millisecond (thousandth of a second). + WaitForLetter Time This command does exactly the same, but does not give you a key unless something other than Shift, Ctrl and Alt is hit. +SetTimer This command sets a timer to the specified number of seconds. +WaitForTimer This command waits for the timer that was set. You have to set a timer or it won't wait. You can use these commands to set the pace of real time game play within your action loop. First you set the timer. Then you do a bunch of stuff. Then you wait for the timer. That way you'll know that each time around the loop takes a certain amount of real time for the person playing. Here is an Example: SetTimer 12.25 Text: Wait for the beep WaitForTimer Wave: Beep There is more about Real Time Game Play further down. (Some additional concepts will need to be introduced, then we will return to the subject of Real Time RPG motion). ++ Creating Voices You can create named voices based upon the three MS TTS voices Mary, Mike and Sam. When you do so, please keep in mind that the speed and pitch of the voices may also be influenced by punctuation, especially the use of parentheses. Here's how to create them: Create Voice VoiceName from MSVoiceName Now that you have created the voice, you could make adjustments to it. There are two kinds of adjustments you can make: Pitch and Speed. Here is an example of all that: Create Voice ClarkKent from Mike Set ClarkKent Speed: 10 Set ClarkKent Pitch: 8 After you create this voice, any time a scene has ClarkKent saying something, the Engine will use the SAPI voice Mike at a speed of 10 and at a pitch of 8. In the first implementation of the Engine the pitch will be ignored. Later that functionality will be added. +++ Moderately Geeky Stuff The stuff below is pretty clear, especially if you take your time. It is important enough that many games will use some of it. Then again, you can still write some great games without it. So I've labeled this next stuff as moderately geeky. ++ Choice Action This subject is interesting enough to deserve its own place to be explained. Since we've covered many of the concepts needed we can do that now. The Choice Action is not really necessary as far as the flow of the game is concerned, because anything the user types will still have to be accepted by a When line in order to result in going somewhere. But if you make good use of the Choice Action it will help out the player a bit as they try to guess what it is that they could or should be doing. All of the crazy things a player might type can first be handled by the Engine, so that you have less to consider when making up your When lines. To make good use of the Choice Action, you need to set it up with the things it needs to know beforehand. Let's start by looking at the responses expected from the player when you use a Choice Action. In a nutshell, it is a sentence, mostly. Since it is always the player doing things, the "I" at the start of the sentence is not used, or ignored if they do type it. Therefore, here are possible formats for a player response to a Choice Action: Verb Example: Fly Verb, Noun Phrase Example: Cast sleeping spell Verb, Preposition, Noun Phrase Example: Fly over moat Verb, Something Example: Eat soon Verb, Something, Something Else Example: Eat some turkey How the engine will allow or disallow player input depends on what the author specifies. (Please find the section on verbs and powers.) There can be more stuff after the verb (and related phrase) that the Engine will ignore. You can deal with that other stuff yourself in the When lines. But this can help you economize on When lines by filtering out many possible goofy responses like "Eat fire" or "Fly under moat", or "Cast Sleeping Spell" when the player has no Powers. It also can help out the player a little by telling them what is basically wrong with their response. Letting them know that they can't cast anything is better than having them try to guess what they can or cannot cast. In order to get the machine to "screen your calls" like that, you need to tell it a few things so it will know what to do. You do that by creating Things, creating People and creating new Verbs. There are aspects about People and Things that you can define. They are called Properties. One important property is Location. Unless your Person or thing is everywhere, it can only be in one place at once. So if you go from where a thing is to somewhere else it is no longer with you, unless you own it. Because if you own it then it is assumed that you brought it along. People cannot be owned, so if they do not choose to go along with you, when you go somewhere else they are no longer around. But if you go back to the last location where you saw them they might still be there. ++ Powers? Abilities? Special Abilties? Capability to do weird stuff? There are politically correct reasons for choosing either Powers or Abilities as the word for this stuff. After much wrestling I have chosen "Has Power to do:" as the specially empowered version of "Can do:". The term "ability" could be mistaken for the normal stuff anyone could do. The term "power" applies to super heores as well as wizards, and even a minister when he marries people, as in "by the power vested in me". ++ Choice Action No NOT This does the same thing as Choice Action, but if the player types something that contains the word "NOT", then they will be told: "I'm interested in what you are going to do, not what you are not going to do. Please try another action." ++ Create Things To create a thing, use this format: Create Thing ThingName Example: Create Thing Doorknob Thing Properties and their defaults: Set ThingName LocationName: Here (where it is, when first created. You can move it by changing this property.) Set ThingName LocationName: Everywhere (You could create atmosphere and have it be everywhere.) Set ThingName Description: Blah blah blah blah (Your description of the thing.) Set ThingName Can Get: *** (It can get anything done to it by anything/anyone unless you specify.) Set ThingName CanGet paint by: *** (It can get painted by by anything/anyone unless you specify.) (Don't say "painted by". Remember a dumb machine will be comparing this to user input.) Set ThingName Can Get: paint (Unless other verbs mentioned, all one can do to it is paint it.) Set ThingName Is: Visible (the opposite of Is: Hidden) Set ThingName Owned by: nobody (things have no owners when first created; you have to set that.) (Once someone owns a thing it is always wherever they are.) Set ThingName Worth: 0.00 (This is the suggested retail price for the thing. You'd have to set it.) Set ThingName (Some property) NOT: The Value This is how you can erase a certain property or property portion that you have set. (It is not really an undo. It just provides a way to get rid of some parts of a property.) Examples of the above construct are: Set ThingName Can Get NOT: paint (It is no longer possible to paint it.) Set ThingName Can Get NOT: *** (It can no longer get anything done to it.) Set ThingName Is NOT: Visible (It is no longer visible.) +++ NOT: and NONE: These two little words are very powerful when it comes to getting rid of certain properties among many that you have set for something. Here is how they work: Suppose you specify the following properties: Set Ostrich Can Get: feed Set Ostrich Can Get: ride Set Ostrich Can Get: cook Having done that, the only things you can do to Ostrich is to feed, ride, or cook it. But what if you want to no longer allow anyone to ride it? Then here is what you say: Set Ostrich Can Get NOT: ride Now the only things that can be done to Ostrich is to feed it or cook it. Let us dig a little deeper to show the full capabilities of this little word. Suppose you specify the following properties: Set Joe Can Do Play trumpet: badly Set Joe Can Do Play trumpet: horribly Set Joe CanDo Play trumpet: well Having done that, the only way that Joe can play trumpet is badly, horribly or well. But what if you want to no longer allow Joe to play trumpet horribly? Then here is what you say: Set Joe CanDo Play trumpet NOT: horribly Now Joe can only play trumpet badly or well, but not horribly. But instead of that, suppose you want to completely remove any limitation about how Joe might be able to play the trumpet? What if he wants to play trumpet wonderfully? You can remove any limitation of his trumpet playing by using this: Set Joe CanDo Play trumpet NONE: blah blah blah Now Joe can only play trumpet any way he feels like. When you say NONE: then everything after the colon is ignored. That's why I felt free to put blah blah blah there. The way these two words work is this: ++ Multi-Line Properties When you keep adding limits to how Joe can play trumpet, you are actually adding lines to a property of Joe called "CanDo". When you say the following: Set Joe CanDo Play trumpet: badly You have added a line to Joe's_CanDo property and the line you have added contains the phrase "Play trumpet: badly". + NOT So when you say the following: Set Joe CanDo Play trumpet NOT: badly the engine searches the Joe's_CanDo property to remove any line that says: "Play trumpet: badly". + NONE Or else when you say the following: Set Joe CanDo Play trumpet NONE: badly the engine searches the Joe's_CanDo property to remove any line that begins with: "Play trumpet:". If a line matches up to the colon it will remove it. Knowing how these two little words work can enable you use them properly, to remove any lines that you have added to any multi-line property. ++ List of Multi-Line Properties Here are the multi-line properties: Access CanDo CanUse CanGet HasPowerToDo Limit Whenever you set one of these properties, the only way to get rid of that setting added to it is to use either the NOT: word or the NONE: word. ++ Create Tools To create a tool, use this format: Create Tool ToolName Example: Create Tool Doorknob Tool Properties and their defaults: Set ToolName LocationName: Here (where it is, when first created. You can move it by changing this property.) Set ToolName LocationName: Everywhere (You could create atmosphere and have it be everywhere.) Set ToolName Description: (Your description of the tool.) Set ToolName Usage: Always (Opposite of learned. Anyone can use this tool right away.) Set ToolName Usage: Learned (Opposite of always. Before a person can use this tool, he has to have his "CanUse" property set to include the name of the tool.) Set ToolName Has Power to do: nothing (The default is no special powers. You have to define one.) Set ToolName Has Power to do open: *** (It can open anything until you specify.) Set ToolName Has Power to do open: door (It can open any door.) Set ToolName Has Power to do: open (It can do nothing but open things unless other verbs are mentioned.) Set ToolName Can Get: *** (It can get anything done to it by anything/anyone unless you specify.) Set ToolName Can Get paint by: *** (It can get painted by by anything/anyone unless you specify.) Set ToolName Can Get: paint (Unless other verbs mentioned, all one can do to it is paint it.) Set ToolName Is: Visible (the opposite of Is: Hidden) Set ToolName Owned by: nobody (things have no owners when first created; you have to set that.) (Once someone owns a tool it is always wherever they are.) Set ToolName Worth: 0.00 (This is the suggested retail price for the tool. You'd have to set it.) Set ToolName (Some property) NOT: The Value This is how you can erase a certain property or property portion that you have set. (It is not really an undo. It just provides a way to get rid of some parts of a property.) Examples of the above construct are: Set ToolName Can Get NOT: paint (It is no longer possible to paint it.) Set ToolName Can Get NOT: *** (It can no longer get anything done to it.) Set ToolName Is NOT: Visible (It is no longer visible.) Set ToolName Has Power to do NOT: open (It can no longer open. Perhaps it can do other verbs.) Set ToolName Has Power to do open to NOT: door (It can no longer open any door.) ++ Create People To create a person, use this format: Create Person PersonName Example: Create Person, ClarkKent (He will be created where you are.) Person Properties and their defaults: Set PersonName LocationName: Here (where he is, when first created. You can move him by changing this property.) Set PersonName Description: (Your description of the person) Set PersonName Is: Player (This makes it so the person is the player playing. These take turns, until each dies.) (When every player dies the game automatically ends.) Set PersonName Can Do: *** (He can do any verb. This is the default unless you specify.) Set PersonName Can Do: nothing (He can do nothing to anything until you specify a verb.) Set PersonName Can Do open: *** (He can open anything until you specify.) Set PersonName Can Do open: door (He can open any door.) Set PersonName Can Do: open (He can do nothing but open things unless other verbs are mentioned.) Set PersonName Can Get: *** (He can get anything done to him by anything/anyone unless you specify.) Set PersonName Can Get paint by: *** (He can get painted by by anything/anyone unless you specify.) Set PersonName Can Get: help (Unless other verbs mentioned, all one can do to him is help him.) Set PersonName Has Power to do: nothing (The default is no special powers. To specify powers use the syntax of "Can Do" and replace "Can Do" with "Has Power to do".) Set PersonName Can Use: *** (He can use any tool he owns unless you specify which tools.) (The tools come with their own definitions of powers.) (The player has to guess what they can do, now that they own it.) Set PersonName Money: 100 (everyone starts out with a hundred, yes definitely a hundred.) Set PersonName Stamina: 100 (when it gets to zero they die.) Set PersonName Is: Visible (the opposite of Is: Hidden) Set PersonName SkillType: BlahBlah (Whatever job title or skills you want: plumber, FigureSkater) Set PersonName SkillLevel: (any number from 1 to whatever. You decide the significance of this value.) Set PersonName PlayerName: Joe Smith (This is the name of the real person who is playing the character.) Set PersonName Score: 100 (This is any number, and to some, irrelevant. Use it how you wish.) Set PersonName (Some property) NOT: The Value This is how you can erase a certain property or property portion that you have set. (It is not really an undo. It just provides a way to get rid of some parts of a property.) Examples of the above construct are: Set PersonName Can Get NOT: paint (It is no longer possible to paint them.) Set PersonName Can Get NOT: *** (They can no longer get anything done to them.) Set PersonName Is NOT: Visible (They is no longer visible.) Set PersonName Has Power to do NOT: open (They can no longer open. Perhaps they can other verbs.) Set PersonName Has Power to do open to NOT: door (They can no longer open any door.) ++ PersonAtBat This is borrowed from baseball. It is the person (fictional character) whose turn it is. Examples: To Set the PersonAtBat: Set PersonAtBat: Albert To Read the PersonAtBat (as a variable) Text: Hello ^PersonAtBat. + NextPlayer This command changes the PersonAtBat, allowing multiplayer game play. + Relative MapAddresses You can specify a MapAddress based upon the one given (or assumed) for any point or location. First you copy it, then you change one detail. Example: Location: Upstairs MapAddress: Same as Downstairs AboveBelow: AboveBelow + 15 End MapAddress ++ Verbs You can make new verbs and set their properties too. To create a verb, type: Create Verb VerbName Example: Create Verb Fly What kind of a property would a verb have? They have limitations. You can define it better by limiting the ways in which it can be used: Limit Verb Fly over: *** (The player can only fly over whatever.) Limit Verb Fly from: *** (Add these two lines to the one above, and Limit Verb Fly to: *** (the player is allowed to do any of these three lines.) Limit Verb Fly under: Bridge (the above is allowed, but the only thing the player can fly under is a bridge.) Limit Verb Eat: food chunks (you can specify a noun or whatever following the verb. When the engine encounters ) The engine doesn't know or care about what is a preposition. It just knows that if you follow the verb with the stuff before the colon, then whenever the player types the same stuff before the colon, it has to agree with the limitations you have set. And if the colon is right after the verb, then the player's response must start with whatever you have following the colon. As an example of this fact, here is a limitation you can make: Limit Verb Play trumpet: badly Whenever the player types that they Play trumpet, they have to follow it with something that contains the word "badly". They would be allowed to type: "Play trumpet so badly that everyone stuffs their pudding into their ears." The limitations you place on verbs themselves are added to whatever disabilities you have given the Person, in order to restrict the possible allowable player typed input. If a player types something not allowed, they will be told what is wrong with it. For example, they would be told: "You can play trumpet, but not like this." + Observe There is a verb that already exists even before the game begins. The verb is called Observe. When anyone successfully Observes, the narrator reads out loud the Setting, along with a list of People and Things that are visible. + F11 Key is the Hot Key for observe Any time the user hits the F11 key the observation is recited. ++ How much do you "see" when you observe? That depends upon the distance of whatever you might see, and a couple properties. + Location's_Visibility Each location has a property called Visibility. It is assumed to be 300 feet, unless you change it with an equation. (Using properties as variables in equations is covered later below.) When you observe, how much detail you get depends upon the distance and the location's visibility. + CanRecognize Another property that determines what you hear when you observe is CanRegognize. It is literally a list of whatever your character knows to recognize, no matter if it's a person, place or thing. If it's on the list then you get the full name of it. If it's not on the list then you just get the general category. Also, if it's almost too far away to see then all you get is the category. Locations are easier to make out from a distance, though. If a thing, tool or person is so far away that it is near the limit of visibility, you won't specifically recognize them, but you'll know what general group they belong to, such as troll, person, busdriver, cop, thing, tool, weapon, etcetera. If you don't know them to recognize them then that's all you'll get anyway, even close up. This is where the ability to create subgroupings really comes in handy. You can create a subset of location called doorway. The immediate parent category of a location would be doorway instead of location, so unless the player could recognize the doorway, all they get is "doorway". This helps you keep the suspense going. Similarly, if a player knows a certain person then they get their name when they observe, otherwise they get something like "policeman". This will vastly enhance the realism if you use it right. + Grab Thing There is another verb that already exists even before the game begins. The verb is called Grab. When anyone successfully Grabs a thing, they own it, and it is put away. It is assumed that any weapon is only visible while it is being weilded, therefore the normal state of an owned weapon is still invisible and thus cannot be grabbed. + Give Thing to Person This is self explanatory. The new owner owns it and the old owner does not. This is not the same thing as to sell. The game author will have to babysit the complexities of selling. (Remember that the beard salesman likes to haggle.) ++ Powers You can make new Powers and set their properties too. A Power is a verb that can only be done if the character has acquired such a Power. To create a Power, type: Create Power PowerName Example: Create Power Fly Now you can define it better by limiting the ways in which it can be used: Limit Power Fly over: *** (The player can only fly over whatever.) Limit Power Fly from: *** (Add these two lines to the one above, and Limit Power Fly to: *** (the player is allowed to do any of these three lines.) Limit Power Fly under: Bridge (the above is allowed, but the only thing the player can fly under is a bridge.) Limit Power Cast: sleeping spell (you can specify a noun or whatever following the verb.) Once a Power is so defined, the player's character has to have that Power or else their attempt at doing so will be denied. If you don't define Fly as a Power, the player will be allowed to type that, and will get a very vague error as you have no When line to deal with it. But as soon as you do define the Power called Fly, the player's character has to specifically have that Power or else the Engine will simply say: "You don't have that Power. What will you really do?" + A Thing can have a Power. The owner of the thing has the Power as long as they own the thing. If they give the thing away, they also lose the Power and the new owner now has the Power that belongs to the thing. Thus if you create a FlyingCape, then endow the FlyingCape with the Power Fly, the owner of the cape can successfully Fly. + ObserveRemote LocationName There is a Power that already exists even before the game begins. The Power is called ObserveRemote. When anyone successfully ObserveRemotes, the narrator reads the remote Setting, along with a list of People and Things that are visible at that remote location. Example: ObserveRemote HomeFrontDoor (tells you all about it) Please keep in mind that the Engine only knows what it has experienced. Therefore, if your character is going to ObserveRemote a place that has not been visited yet, you are going to have to at least teach the place to the Engine. That can be done by quickly and silently visiting every location during the chain of choiceless situations at the start of the game. As you go to each location, you can establish the setting, and create any people or things that are at that location. There is much setting up to do at the beginning of the game anyway; this will just mean a little more. ++ Automate Verb ++ Automate Power You can automate Verbs and Powers. If you do so, then every time a player is successful at using a verb or Power, and before it gets evaluated by the when line, a certain Function will be performed. The function will have the same name as the verb or Power, and the engine will give it the temporary variable ^^Action, which is filled with the entire action as typed by the player. This is a handy way of updating things that need to be figured out before testing the action with when lines in the choice. If you automate a function but you have not run the situation where the function is defined, then no automatic actoion will be done. Just like anything that is remembered by the engine, the engine has to experience it or it doesn't exist yet. The automate property of any verb or power is set to "True" by default, which means that unless you set it to false, if a function has baeen learned that has the same name as a verb or power, that function will be launched whenever the player successfully uses that verb or power. +++ How Choice Action Works Now that I've introduced the major concepts, I can explain how the Engine decides whether or not to allow a certain action that the player types during a Choice Action. When you have a Choice Action, the player is prompted to type something. Hopefully they will type something resembling an action. If their typing begins with the word "I" then that will be stripped off of what they type, leaving just the action that they intend to do. Before the action they have typed is ever allowed to be compared against the when lines that follow, the action must itself be compared against all of the properties that the game has set up. If the action is found to not be allowable, the engine will do its best to tell the player in a specific way what is wrong with it. Then the player will be allowed to try typing an action again, until they have typed something good enough to compare with the when lines. What determines whether an action is good enough will now be explained. First of all, if the player types "I" or "I'll" or "I will" or "I choose to", then all of that gets stripped off, leaving the verb as the first thing on the line. Next, the engine considers who is the person at bat. The character whose turn it is has certain properties that may decide what verbs can or cannot be used, as well as how they may or may not be used. If the player's CanDo property puts a limitation on the verb in question, then rest of the phrase is checked against all such limitations. For instance, suppose Joe is the character played by the player. Suppose the following line had been run: "Set Joe CanDo Play: instrument". Then the only thing that Joe can play would have to be something that can be called "instrument". If the player then types "Play Football" then they are not allowed that action. They will be told "You may be able to play, but you cannot play football. Please try a different action." But suppose the player had typed: "Play a musical instrument well". Then the engine would find the word "instrument" and allow the action. So much depends upon where you place the colon! Let us prove that with another experiment. Suppose the following line had been run: "Set Joe CanDo Play instrument: badly". Then the only way Joe can play something called "instrument" is badly! Yet Joe is allowed to play football all he likes, because everything before the colon sets up a circumstance, while everything after the colon limits what can be done within that circumstance. In this case, if the player types: "Play instrument so badly everyone's ears bleed", then the following is true: Because the word "instrument" follows the word "play", the limit has effect and needs to be considered. Yet because the word "badly" follows the word "instrument", the limitation regarding "Play instrument: badly" is satisfied. Therefore the action is allowed. But what if "instrument" happens to be the name of a thing you have created? Then the engine will have to look at the properties of "instrument" to make sure nothing prevents it from being played. Suppose some picky instrument owner has determined that their instrument shall only be played well, or else not played at all. In that case, since the only way that Joe can play instrument is badly, Joe does not get to play! The setting that would accomplish that is: "Set instrument CanGet play: well". Now Joe is allowed to do anything he wants to that instrument except play it, since the only way he can play instrument is badly. To protect the instrument from being destroyed by an angry Joe, while also protecting our sensitive ears, the owner should have caused there to be two settings: "Set instrument CanGet: play" and "Set instrument CanGet play: well". The combination of those two settings would make it so that the only thing that can be done to instrument is to play it, and the only allowed way to play it is "well". So far we have been matching action words directly. There is an indirect way to match them also. If we have created a category called "instrument" and we have created an item within that category called "trumpet" then Joe would not be allowed to play trumpet badly either. Our ears are safe, for the time being. And so is the trumpet. There is another setting that could have protected our ears. Suppose a friendly wizard with sensitive hearing cast a spell over the land so that no bad music could be heard. This would be accomplished by limiting the verb "play". This merciful setting is "limit play instrument: well" Now for a word of caution. Joe has just been through a situation called music law. He does not play any better, but he has learned to abuse the language of music. The player now types: "Play trumpet hardly well at all", and sadly, Joe is allowed to do that to our ears, because the word "well" follows the word "trumpet". Let us hope that the game author prevented such abuse by means of well written when lines. That is the word of caution. Sometimes you will have to prevent bad actions by using the when lines. Here is an example. Suppose Joe tries that sneaky trick again. The player types: "Play trumpet hardly well at all". The when lines that follow are not fooled. Here are the when lines you can put, that will protect our hearing. When not ~and well" Text: I simply cannot allow you to do that to my ears. GotoSituation: Same When hardly ~and well" Text: I simply cannot allow you to do that to my ears. GotoSituation: Same Instead of merely putting "Choice Action", the game author could have put: "Choice Action No NOT". In that case, if the game player had typed "Play trumpet not well at all" then he would have been told: "I'm interested in what you are going to do, not what you are not going to do. Please try another action." It is sadly true that Joe found a dodge around even that, but in most cases this will work nicely. ++ Refresh Object Now one more wrinkle to discuss. Suppose the player has to fight a goblin named Screwtape. If all he is told is that a goblin is in front of him, how can he try to smite the goblin with his sword? He can't say Smite Screwtape, because he does not know the goblin's name. But he can say Smite Goblin. Therefore, when the player types an action that makes reference to a group of people or things or tools, the engine will understand that the player is really talking about the most recently created of such objects that is located where the player is. Suppose that during the game, two goblins were created. Their names are Screwtape and Wormwood. If only Screwtape is presently in the same location as the player, then the player can say Smite Goblin, and he will be smiting the goblin named Screwtape. But what if both are located where he is. Then the engine will understand that he is trying to smite the most recently created goblin. If both goblins are fighting the player, how can the game author make sure that the player is fighting the one that he is being most recently attacked by? By using the "Refresh" command, the object will be moved to the most recently created position. Here is an example: Create Goblin Wormwood Create Goblin Screwtape Text "An ugly goblin appears, wearing a shirt with a big W on it. It attacks you." Refresh Wormwood Choice Action Now when the player types "Smite goblin", the goblin named Wormwood gets struck. Of course for this to matter, some more detail needs to be filled in, but the main point of this example is show how to direct the activity to the right member of a group of objects, when the player only knows the group and not the member's name. That is the end of my discussion about how Choice Action works. ++ Music On Hold If the player pauses the game and there happens to be some audio sequence running, it will continue running, unless your create a special audio sequence called MusicOnHold. If you have packed an audio sequence called MusicOnHold, then when a player pauses the game, your MusicOnHold audio sequence will be played. When the player unpauses the game, any audio sequence that was interrupted will start again from the top. ++ EndGame: Blah Blah Blah (You issue this command and message is spoken, and the game ends.) +++ Security ++ Certify your game Suppose you want to make sure nobody offers bogus versions of your game? Simply have the engine certify your game. It will put this stuff into your files: +AuthorCertification: This is where the engine places a special mark it makes to authenticate the author. The game author can publish this on the net and it can be checked against all files. + FileCertification: This is where the engine places a special mark it makes to authenticate the file. Nobody needs to be concerned with this. The Engine will evaluate it for everyone. Only the Game Author knows the Game Author's secret password, which is used to create both certifications. If a user tries to recertify the file without knowing the game author's password it will change the AuthorCertification. If they hand edit the Author Certification it will no longer fit the FileCertification. ++ Encrypt your game The following security features only need to be present in the first GameFile, which is called "GameFile_Start.txt". Once your game has taught the player's engine the following settings they cannot be forgotten except by quitting and restarting the engine. Suppose you have invested a major portion of your life into making an truly awesome game. And suppose you decided that for this game you wanted to be paid something for each copy out there. In that case, this next feature is for you. You could precede your source code in each file with this: Encrypt Then at the end of your file, put something like this: LicenseFile: GameKey.txt OrderURL: http://www.FreakazoidGames.com SendRequest: bigfreak@freakaziod.com DemoTime: 5 minutes. (If you specify 0 then that means forever.) NumberOfSaves: 10 (When any game quits, it allows you to save the game. The game author can limit the number of times a player can save an unregistered game.) GameKeyText: This phrase combines with user name to create individual GameKey (Put whatever you want to put here; it should be the same throughout the game.) (Don't put anything too easy to guess unless you want folks licensing themselves!) (Of course, what you put will not be shown in the encryptred version of the file.) When you have lines such as this in your source and you certify the game file, an encrypted copy of your game file will be made. When the user reads an encrypted file, all they find is one line that says "Encrypt" and then the rest of the file seems like random garbage. I made up a fictitious web site and email to use as an example. When you put your real web site and email address there, the game player won't find that either. But when they want to register your game, the engine will show them how to contact you and what to do. The player cannot read encrypted files, but the engine will play the files just fine. If GameKey.txt is present, that means the player has registered your game, and is allowed to play it for more than the time you specify, in this case, 5 minutes. Otherwise, after 5 minutes of game play, the game will end and the player will be given instructions on how to buy a license for the game from your web site. This is the end of the Security stuff. Now we will change the subject by showing off some cool geek toys. +++ Cool Geek Toys! Warning: Some people may find the following extremely boring. If this is your thing, have fun! Otherwise, at least you didn't have to sit through it all. ++ Special Variables + FunctionName#LineNumber (This is a variable) You can access any line of any function as a text variable. This allows you to have one Function write or edit another Function. Example: Equation: Haggle#1 = "Text: Oh, you can't just buy that beard, you have to haggle!" You have just filled the first line of the function called Haggle. + SoCalled^Whatever#LineNumber The SoCalled method allows you to refer to a Function by the contents of a variable. Example: Equation: ^A = "Haggle" Equation: SoCalled^A#1 = "Text: Oh, you can't just buy that beard, you have to haggle!" You have just filled the first line of the function called Haggle. + Item's_Properties You can access any property of any Item as a variable. Any item, like a person, Location, etc has properties that you can access. Example: Equation: ClarkKent's_Age = 42 + SoCalled^Whatever's_Properties The SoCalled method allows you to refer to an item by the contents of a variable. Example: Equation: ^A = "ClarkKent" Equation: SoCalled^A's_Age = 42 Now ClarkKent's age has been set to 42. + ^QuoteMark (This is a variable that cannot change) This is a system variable that stands for a quotation mark. You can use it in processing portions of text that contain quotation marks. + ^CRLF (This is a variable that cannot change) This is a system variable that stands for carriage return and line feed. You can use it in processing portions of text that span more than one line. +++ Using Quotes When you put: Equation: ^A = Hello the engine fills the variable ^A with the word Hello. But suppose you use another variable name instead of Hello? If you put: Equation: ^A = ^B the engine will go look up the contents of ^B and fill ^A with it. What if you want to set a variable to be equal to the name of another variable? You can do that by using quotation marks. Example: Equation: ^A = "^B" This brings up a thorny issue in language, namely, trying to know what you want done. To resolve that, I have settled upon the following behavior. I will give some particular punctuation, and some special commands you can use in order to do what you have in mind. To make all this work, I invented a few new operators that I will call TildaOperators. They go right after the equals sign, and you can only use one of them at a time. I will introduce them one at a time by showing how they are used. Here we go: When you put: Equation: ^A = ^B it fills ^A with the contents of ^B When you put: Equation: ^A = "^B" it fills ^A with the variable name ^B When you put: Equation: ^A = ^QuoteMark ^B ^QuoteMark it fills ^A with the variable name ^B When you put: Equation: ^A = ^QuoteMark & ^B & ^QuoteMark it fills ^A with the phrase: & ^B & Surprise! The ^QuoteMarks protect the entire phrase from being solved. Therefore the only solution is to remove the QuoteMarks, leaving just the phrase inside, including the surrounding & ("And") signs! When you put: Equation: ^A = ^B + ^C it fills ^A with the solution to the expression ^B + ^C When you put: Equation: ^A = "^B + ^C" it fills ^A with the expression ^B + ^C (The solution to anything in quotes is simply to take it out of quotes.) Suppose you want to solve that expression that you had copied into ^A? When you put: Equation: ^D = ~solve ^A it fills ^D with the solution to the expression that you had copied into ^A. Example: Equation: ^A = 4 + 2 Equation: ^D = ~solve ^A it fills ^D with 6 When you put: Equation: ^D = ~solve "^A" it fills ^D with the variable name ^A (The solution to anything in quotes is simply to take it out of quotes.) When you put: Equation: ^A = ~AddQuotes ^B it fills ^A with the contents of ^B, surrounded by quotation marks. When you put: Equation: ^A = ~AddQuotes "^B" it fills ^A with the variable name ^B, surrounded by quotation marks. When you put: Equation: ^A = ~LoseQuotes "^B" it fills ^A with the variable name ^B When you put: Equation: ^A = ~LoseQuotes ^A any quotes surrounding the contents of ^A would disappear When you put: Equation: ^A = ~LoseAllQuotes ^A any and all quotes in the contents of ^A would disappear +++ Special Commands Here are some special commands you can put in your game file to do certain things. + SaveFunction FunctionName as FileName (this is a command) This saves any function as whatever the name chosen is. It will overwrite if need be. (If the game is encrypted, this will save the function in encrypted form.) + LoadFunction FunctionName from FileName (this is a command) This loads a function from the hard drive into memory, as if create function had been performed. + SaveVariable VariableName as FileName (this is a command) This saves any variable as whatever the name chosen is. It will overwrite if need be. (This is essentially a debuging tool. An encrypted game cannot save a variable.) + LoadVariable VariableName from FileName (this is a command) This loads a variable from the hard drive into memory, and if the variable does not yet exist it will create the variable in memory in order to fill it from the hard drive file. (This is essentially a debuging tool. An encrypted game cannot load a variable.) + Destroy Anything that can be created can be destroyed. The only thing that could be automatically destroyed is people. When they have zero stamina, they die and are destroyed. Any things they had owned had spilled from their bag when they fell over, and are visible. Those things are located in the last place where the person had been alive. One can take inventory of those things by Observing. This is a good way to plunder fallen enemies. + Start FileName Argument This geek toy launches a program or a file. Example: Start Winword.exe AudioAdventureFormat.txt Try typing this from your msdos prompt and you will find what it does. In the game engine it acts the same. You can put this command anywhere. If you have cool programs that you can invoke to perform special effects, here is how you can trigger them to do things at certain times in your game. ++ Higher Math functions: The following Higher math functions are included. (You can ignore this section if you wish, but it's nice to know it's there if you need it.) x >to>the> Y gives x to the y Power [Exp](x) gives the natural log of x [Sgn](x) gives the sign of x (as in negative or positive) [Sqr](x) gives the square root of x [Atn](x) gives the arctangent of x [Tan](x) gives the tangent of x [Sin](x) gives the sine of x [Log](x) gives the base ten log of x [Cos](x) gives the cosine of x [Sec](x) gives the secant of x [Cosec](x) gives the cosecant [Cotan](x) gives the cotangent of x [Arcsin](x) gives the inverse sine of x [Arccos](x) gives the inverse cosine of x [Arcsec](x) gives the inverse secant of x [Arccosec](x) gives the inverse cosecant of x [Arccotan](x) gives the inverse cotangent of x [HSin](x) gives the hyperbolic sin of x [HCos](x) gives the hyperbolic cosine of x [HTan](x) gives the hyperbolic tangent of x [HSec](x) gives the hyperbolic secant of x [HCosec](x) gives the hyperbolic cosecant of x [HCotan](x) gives the hyperbolic cotangent of x [HArcsin](x) gives the inverse hyperbolic sine of x [HArccos](x) gives the inverse hyperbolic cosine of x [HArctan](x) gives the inverse hyperbolic tangent of x [HArcsec](x) gives the inverse hyperbolic secant of x [HArccosec](x) gives the inverse hyperbolic cosecant of x [HArccotan](x) gives the inverse hyperbolic cotangent of x [BaseYlog](x) gives the base Y log of X I offer no guarantee that these functions work. I have tried to faithfully reproduce the published equations, but I have not tested the results. If I made a typo that results in a gross error, please let me know and I'll check the specific function. You obviously don't need all this, but at least now you have what it takes to go wild into math if that is your thing. +++ Extending the Language While what is already in the language is stable, it is possible to add new aspects. This is done by performing library files containing situations that have no choices. All they do is set up things at the beginning, before actual game play. In many cases these files merely set up the particular game. But it is also possible to set up the language to be more fully complete, using the same kind of library files. A perfect example of this would be a new verb called sell, that triggers an entire haggling procedure. (And we know how much the beard salesman likes to haggle!) Even more extensive additions can be made, such as adding the verb walk, which would trigger a whole procedure that gets from the player the general direction, then interacts with the player to cause them to arive at the nearest available location in that direction. Wouldn't it be nice to have the location become a part of this decision making? Well, there is one more thing needed to extend the language to do so. What if you could add more properties to persons, places and things? Then you could add a property to any location, connecting it to another location in a certain direction. That way you could have the walking dialog know that you cannot get from the hall into the living room except by way of the door. By adding to a property like "Connected to", you could make a list for any location of the other locations from which the player can reach it by walking. This is only one example of how creating properties could enhance the language. To accomodate all of the untold possibilities, the following constructs are now added to the format: + Create SubCategory SubCategoryName of MainCategory The main categories are Person, Location and Thing. You can create subcategories of these. An example would be to make a subcategory of person called wizard. You will know the purpose of this in a moment. + Create CategoryName SomethingName An example of this is Create Person ClarkKent. The category used in this can be any main category or subcategory. Now that you have made subcategories and populated each grouping (subcategory) with persons, locations and things, you can do the next step. (Notice that an item is a something, not a variable, so it does not use a Carat.) + Create Property CategoryName PropertyName Once you do this, you can refer to this property of every item within the category. An example is Create Property MagicQuanta Wizard. Now you can refer to the quanta of magic (magical energy level) of any wizard as a variable. If ClarkKent is a wizard then you can say Set ClarkKent MagicQuanta: 100. ++ Extra Wave commands You can do more with wave files than merely play them. You can also modify three of their properties, either before playing them or after. If you modify beforehand then when you play them they will start at the settings you want. Here's how you modify wave sounds: NextWaveSpeed 80 (The next wave sound that plays will play at 80 percent normal speed) NextWaveVolume 80 (The next wave sound that plays will play at 80 percent normal volume) NextWavePanning 50 (The next wave sound that plays will be centered in panning) WaveSpeed MySound 80 (A sound file called MySound that is already playing will slow down to 80 percent of the present playing speed). WaveVolume MySound 80 (A sound file called MySound that is already playing will continue playing, but at 80 percent of full volume). WavePanning MySound 90 (A sound file called MySound that is already playing will continue playing, but it will now be located way over to the right.) + ^UpXXFrets and ^DownXXFrets There are system variables you can plug into the WaveSpeed command to make it shift the wave sound up or down a certain number of frets (chromatic steps). Example: WaveSpeed MySound ^Down24Frets (knocks the sound down by two octaves). + Multiple instances of the same wave file: Now you can use the same wave file simultaneously by giving it an index or key. Examples: Wave: C:\Windows\Media\Tada(1) loop Wave: C:\Windows\Media\Tada(2) loop Wave: C:\Windows\Media\Tada(C#) loop Wave: C:\Windows\Media\Tada(A) loop If you do this you will have four different wave sounds by those names, all loaded from one real file. Here is another cool thing: + ^UpXXFrets and ^DownXXFrets There are system variables you can plug into the WaveSpeed command to make it shift the wave sound up or down a certain number of frets (chromatic steps). Example: WaveSpeed MySound ^Down24Frets (transposes the wave sound down by two octaves). WaveSpeed MySound ^Up60Frets (transposes the wave sound up by five octaves). + Now you can have any number of wave sounds at once. The Engine only creates as many buffers as it needs. Normally, whenever you request a wave sound, the Engine first looks to see if you already have that particular wave sound loaded already. If so, it re-uses it with the previous settings. That saves all the time it would take to reload that wave file from memory all over again. If it does not find it, then it will look for the first buffer that is not playing any more. If it can't find any presently unused buffers then it will create another buffer and use it. But what if the wave file you wanted to re-use got overwritten by the Engine for some other sound? + PermWave and KillWave You can tell the Engine to play a sound, and then hang onto it for future reference. You do this by using the PermWave command. The next time you issue the Wave (or PermWave) command for the same sound the Engine will go find the one you wanted to keep in memory and play it from there, with all of your settings intact. When you are done with a sound you can then use the KillWave command. Examples: PermWave: C:\Windows\Media\Tada loop (creates and uses a new buffer for Tada) StopWave: C:\Windows\Media\Tada (stops the tada wave from playing) Wave: C:\Windows\Media\Ding (creates new buffer instead of overwriting tada buffer) PermWave: C:\Windows\Media\Tada loop (re-uses the old tada buffer to resume tada playback) + EndlessLoop Normally a wave sound that loops will end when the function or situation that played it ends. But if you want a wave sound to keep looping no matter what until you stop it, you can use the commmand called EndlessLoop. Example ~Situation Name: First Wave: MyBackground EndlessLoop Text: Hear the background sound. Pause: 7.00 GotoSituation: Second ~Situation Name: Second Wave: MyBackground EndlessLoop Text: Notice it did not skip to the top, but just kept looping normally. Pause: 7.00 GotoSituation: Third ~Situation Name: Third StopWave: MyBackground Text: Notice it finally stoped when you finally told it to stop. Pause: 7.00 EndGame ++ Create AudioSequence AudioSequenceName This allows you to preprogram sequences of audio sounds to be performed at any time. The syntax for creating it is shown here. At the end of your sequence you should put "End AudioSequence". Within your AudioSequence description you should put information about what you want to happen. You can play a wave files and or do stuff with midi. Midi is composed of 16 channels, one of which is drums. You need to know your way around midi to use this feature. There are plenty of midi tutorials on the internet. This engine uses a certain syntax to do this stuff: Create AudioSequence MySequence Description: (Put your text description of the AudioSequence here.) Wave: (Same rules as for any wave statement. Find the Wave section later for details.) MidiChannel: 1 (Anything you do about midi will be now pertain to Midi Channel 1) (You can use any channel here, not just 1.) Volume: 100 (This sets the MidiChannel you're dealing with to a Volume of 100) Panning: 127 (This sets the Midi balance, which is called panning, to 127) Instrument: 1 (This sets the instrument to 1, for the midi channel you selected.) NoteOn: 40 (This turns on midi note 40 for the selected channel) NoteOn: 40 @ Velocity: 100 (This turns on midi note 40 at velocity 100 for channel.) NoteOff: 40 (This turns off note 40 for the midi channel that has been selected.) Wave: (This acts just like any other Wave: statement.) Pause: 1.00 (This makes the AudioSequence pause 1 second before continuing.) End AudioSequence (This concludes the defining of the audio sequence.) NOTE: The pause: command is in seconds, (but has a resolution of a millisecond). If your timing is down to the millisecond level (thousandth of a second), please keep in mind that the program itself also takes a few milliseconds to think about what it's doing. NOTE: (pun) You can use equations and variables in your AudioSequence. But be forwarned, some really complicated equations might take a noticable fraction of a second to calculate, so your timing could be affected. Examples of such stuff is here: Create AudioSequence Scale MidiChannel: 1 Volume: 100 Panning: 127 Instrument: 1 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 2 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 2 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 1 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 2 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 2 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote Equation: ^MyNote = ^MyNote + 2 NoteOn: ^MyNote Pause: .20 NoteOff: ^MyNote End AudioSequence Now if your function contains this: Equation: ^MyNote = 36 Perform AudioSequence: Scale Equation: ^MyNote = 48 Perform AudioSequence: Scale Equation: ^MyNote = 60 Perform AudioSequence: Scale Equation: ^MyNote = 72 Perform AudioSequence: Scale It will sound like someone ran their hand up a few octaves of the piano keys. You can also issue midi commands outside of an AudioSequence, but the nice thing about doing it inside of an AudioSequence is that when an AudioSequence ends, it cleans up after itself by turning off all the midi notes that it ever used. That helps to assure that you won't get any stuck midi notes. If you are careful to do the same thing, you can use midi anywhere you want. If an audio sequence is already running when another is triggered, the new one will turn off all midi notes from the old one and begin its own midi. ++ Wave sounds and layering: The following commands are useful in layering wave sounds: Wave WaveFileName (starts a wave sound playing) Wave WaveFileName Loop (starts a wave sound playing in a continuous loop) Pause TimeInSeconds (the audio sequence, function or situation waits the time) StopWave (stops all wave sounds) StopWave WaveFileName (Stops just the named wave file. If that particular named wave file isn't presently playing, then it will stop all wave sounds.) You can now layer wave sounds. You can have up to four Wave sounds playing at once. This allows you to create some nice textures out of 3 looping wave sounds and use the last wave channel for certain effects, without ever interrupting your nice layered texture. If you already have four wave sounds playing at once and try to start a fifth one, the last wave file started will be interrupted. The DirectX version won't have this limitation so it's better not to rely on it. In the following example I purposely stoped the fourth wave befoire starting the fifth: Wave DistantTraffic Loop Wave MuffledTalking Loop Wave KitchenNoises Loop Wave PersonEatingTooQuickly Loop Pause 7.5 StopWave PersonEatingTooQuickly Wave PersonChoking Loop Pause 5 Wave PersonFallsOnFloor StopWave MuffledTalking When you perform the above example it sounds like you are in a restaurant. You can hear distant traffic, muffled talking and kitchen noises in the background. In the foreground you hear a person eating like a pig, much too quickly. You hear them eating like this for 7 and a half seconds, then you hear them choking for 5 seconds, then you hear them hit the floor. After that, the person is strangely silent, and so are the patrons of the restaurant. Only the distant traffic and kitchen noises continue. + If Then Otherwise EndIf You can decide what do based upon a certain condition. An equation such as "Equation: ^A = ^B + ^C" will set ^A to become ^B + ^C. But what if you want to know if ^A already is equal to ^B + ^C? You can do that by testing it with the IF statement. Here's how it works: Instead of the word "Equation:", you use the word "If". Now, just like in the English language, you have to say what will happen If the If is true. If somebody says: "If you even think about it..." then of course the smart answer to that is: "Then what are you going to do about it?". You can use similar words in the wizard's language. For example: If ^A = "Whatever" Then Text: This is True Otherwise Text: This is not true End If When this is performed, if ^A is equal to "Whatever" then the text that is spoken will be "This is true". Otherwise, you'll hear "This is not true". You don't have to have an otherwise, but you can if you want to. The if statement does not use wildcards, but it is willing to consider the following kinds of facts: If ^A = Expression (If ^A is the same number or the same text as the expression's result) If ^A <> ^B + ^C (If ^A is not the same number or the same text as the expression's result) If ^A < ^B + ^C (If ^A is a number less than the expression's result) If ^A > ^B + ^C (If ^A is a number greater than the expression's result) If ^A contains SearchExpression (This is similar to the when line but no wild cards.) Example: If ^A contains cat ~or dog ~and chow ~or food You can also say: If ^A = ^B Then Text: Hello End if (The Engine will put it together that way anyway, but I think the first way is more clear.) + Choices without any Goto You can have choices without any goto in them. The when lines for the choice can be where you perform certain Texts, Equations, Functions or other stuff, depending upon the when line coming true for that choice. You can even have a tiny choice inside a when line. You have to be careful if you are putting choices inside of choices. If you forget to end the choice you can really confuse everything! ++ Differences between Situations, Functions and AudioSituations There are three kinds of script: Situations, Functions and AudioSequences. You can put a surprising amount of stuff into Functionsthat would normally be found in situations. There are also some differences between Functions, AudioSequences and Situations: + Situations can be played straight from the file, without having to be memorized first. + Functions and AudioSequences must be learned by the game before they can be performed. + Only a situation can "goto" a situation. If a situation ends without a "goto" then it first tries to resume where it left off from the situation before, and if that doesn't work, the game ends. There is not a stack of places to return to, because it only looks one situation back for a place to return. + Functions and AudioSequences always return to the place from which they were called, so you might build up a stack of them inside each other, and the stack will dwindle to nothing as each one returns to where it came from. + AudioSequences are the best way to do midi, because they clean up after themselves. + Functions and Situations can do midi, but you have to be careful to shut off all the midi when you are done so you don't leave a stuck midi note hanging. This allows you to leave a note active while you go from one situation to the next, perhaps for a motor noise or something. You can make an empty AudioSequence and perform it anytime you want to make sure all the midi is turned off. There is also a hot key the player can press (F9) to shut off every midi note, just in case. + AudioSequences can happen at the same time as game play! The five gallon word for this is that AudioSequences are asynchronous. What the heck does that mean?! Once you start an audio sequence, it keeps going and yet at the same time, the game does not wait for it to finish, but the game can also keep going. This is especially useful when you want to set up some random noise background and at the same time allow the playing of the game to continue. It is much more fun to keep hearing all the realistic background sounds while you respond to each situation. + Commands available for an AudioSequence: To prevent a world of woes, the possible commands within an AudioSequence are limited to the following set: MidiChannel Volume Panning Instument NoteOn NoteOff PresetPause Pause If Then Otherwise EndIf StartLoop RepeatUntil Wave StopWave Choice Variable When EndChoice Equation 'REM + Preparing a Pause to be Super Accurate! Did you notice that command caled PresetPause? You can use that to make your Pause timing really accurate. Here's how it works. First you say PreparePause. That is like starting a stopwatch the moment you said it. Then you can do a bunch of stuff, and then after that you can use the Pause command. Instead of waiting a certain time after you gave the Pause command, it waits a certain time after your had originally given the PresetPause command. For example: PresetPause (starts the stopwatch ticking, so to speak) PerformFunction "^MyFunc" (this function sometimes takes half a second, sometimes three.) Pause 3 Text: Done! When these lines are performed, the Text "Done!" is delivered exactly 3 seconds after the first line is performed, even if the function in the middle takes 3 seconds or only a half second to perform. ++ Descriptions of Pictures and Wave sounds: You can use pictures and wave sounds in your game. Following the line that says "Wave:" or "Picture:", you can have a line that says "Description:". When you certify your game, or when you first test it, the Engine will check to make sure that every wave file and picture has a text description. It will first look for a text file by the same name as each wave file or bitmap file. If it finds none, it will search through all of your game files for a "Description:" line for that sound or picture. If all else fails, it will perform the sound or picture for you and ask you to describe it. When the Engine finds a description or has you type one, it makes the text description file for you so that you don't ever have to deal with it again. This is an extremely easy process and won't cost you any noticable amount of time. In this way, no matter who makes a game for whom, it will be accessible to all, with no real extra effort. In the rare event that one has absolutely no desire to provide any description, they can simply type "none" when prompted, and the engine will store that, allowing it to use the file name itself as the description. Then later if someone writes a set of third party, after market descriptions, such a package can be opened up into the game directory, making such a good game accessible for all. + Important: Blah Blah Blah (The rest of a picture or wave description) If you start your picture or wave sound description with "Important: " then when the player has selected (from the engine's menu) "Just the Important Descriptions" for the pictures or sounds, they will be told or alerted to only those descriptions that you have marked as important. This is an intermediate setting between "All Descriptions" and "No Descriptions", designed to help things move along smoothly during game play. When you are making descriptions for your sounds or pictures, if you think that something important about the game can be learned from the description, you can mark it as important. If your sound or picture is not really important, but merely entertaining, you can just give it a normal description without saying it is important. ++ Colons: I thought about making them optional. There are some places where we just can't get along without them. Examples are when a named voice talks (like in a play), as well as when you set properties or limit verbs and powers. When in doubt, download the latest version of this paper and then use the same punctuation that I do. ++ A Word About FileNames and VariableNames In creating this language, one of my big goals has been to make it self documenting. In other words, if you grab some source code and read it, it is fairly close to plain English, and very easy to understand. In my own programming, I may never know how many hundreds, perhaps thousands of hours worth of confusion I have avoided simply by creating meaningful names for my variables and files. If you do the same, not only will you help to enhance certain accessibility features, but you will also find your own games easier to come back and understand later. The easiest way to make meaningful names is to run carefully chosen words together, with the first letter in each word capitalized. If you look at my layered wave file example you will know just what I mean. + Capitalization Keywords are not case sensitive. Neither are file names. Neither are the names of variables and properties. The system stores them in all lower case, but I certainly hope that you will write your games with good capitalization, for your own benefit. And of course, the contents of all those things are not converted to lower case. When the engine compares text it ignores the case (capitalization), but it does not alter any text. ++ ForceSituation In some very rare cases you might want to force the game to give up all other activity and start doing the situation you desire for it to do. An example of where this would be useful is in a verb function called fly or walk, where you could have the real time actions of user cause them to wander into a certain situation. In such a case you set up the GotoFile like you normally would in any situation, then instead of GotoSituation you say ForceSituation. Example: Create Function JumpToTop GotoFile: Same ForceSituation: Anything EndFunction When the Function shown above is performed, the game will quit from doing whatever it is doing, and will instead find the first situation it can find within the present file, and will begin playing from there. +++ FrozenMenu Function Whenever the person playing the game hits the F8 key, the Engine launches a Function called "FrozenMenu" if present. It is up to the game author to write this function. What I recommend for this function is a WaitForLetter command followed by a choice variable command. The when lines of this choice variable would launch functions. In this way the player can hit F8, then a certain letter to access a certain feature written by the game author. The function can even have a voice mail type dialog. It is up to the game author what will be there. When the FrozenMenu function ends, it naturally returns to wherever the game was. +++ Real Time RPG Motion You can create a function that contains a loop. Each time the loop is performed, the player gets a chance to hit a key. Whatever key they hit does something special. That way you can have them use the keyboard as a joystick. The following vartibles play a part in doing this: ++ ^PretendTime ^PretendTime is a system variable that is used almost like the clock at a football game. You can set it going in real time, you can freeze it (like in "time out"), you can set it ahead a certain amount, and there are also certain activities that will automatically move it ahead, corresponding to how long some things take to happen. + StartPretendClock (starts the PretendTime clock running.) + StopPretendClock (stops the PretendTime clock.) ++ DirectionFacing DirectionFacing is a property of every person (and monster). It stands for which way they are facing. It is expressed in degrees, so it can be anything from 0 to just a sliver short of 360. North is 0, East is 90, South is 180, West is 270. You can also set it by hour:minute as it appears on the face of a clock. We shall assume that every monster has excellent hearing, so they will turn themselves as required to deal with anything nearby, and as required to shoot at you. (If you want to create a situation where a player can sneak up behind a monster, you would need to change the monster's aggressiveness based upon what you decide he can see and hear, and your code would decide that with equations based upon distance and directionfacing.) ++ Pitch This is usually zero. Pitch is positive if you are facing upward like an airplane that's climbing, and negative if you are facing downward like an airplane that's diving. Pitch is in degrees. If your pitch is 180, you are flying upside down and backwards! Pitch is a property of a person. ++ Radius and Height This determines how far away something has to be for you to bump into it. Your AboveBelow property of your MapAddress pertains to the lowest portion of your body. Above that, you are presumed to be six feet tall. You are also presumed to be two feet in diameter, which is a radius of one foot. This defines your shape unless you change those properties. Your shape is considered in detecting collisions. ++ Speed Speed is how fast the player is moving when they move in whatever direction they are facing. ++ Aggressiveness Aggressiveness is a property of all people and tools. Normally a tool is not going to be aggressive unless it is something like a robot with a personality problem. ++ Visibility is a property of the leg of a journey, which is something that I will talk about very soon. It is measured in the same units of measure as one of the dimensions of a MapAddress. The following commands can be used within that loop to save you a lot of programming work while doing some pretty impressive game play: ++ Turn It takes no pretend time for someone to turn. You simply say how many degrees. If the number you give is positive, their DirectionFacing is rotated clockwise that number of degrees. If the number you give is negative, they will be rotated counter- clockwise. If the number is greater than 360, we will assume that they do not get dizzy. ++ Face This is just like turn, but the number you give sets the absolute direction that the player is now facing. If you say Face 0 then they are now facing north. In other words, you have just set their ^DirectionFacing property to zero. ++ 2DRadar and 3DRadar The Engine has radar systems that tell the player about accessible and inaccessible locations such as doors and walls, as well as things, tools and persons along with their dispositions such as giving chase, fleeing or oblivious. There are two types of radar readout. Those two types are 2dRadar and 3dRadar. You can also issue them as commands. Whenever the player turns, faces or moves, the radar should be used. The radars give midi note concept of what is going on, and then give speech concept. You can interrupt the speech it gives by causing other speech. To issue a Radar command in code, put: 2DRadar or 3DRadar. The two kinds of radar sound and behave differently. If the player is either flying or being attacked by something that is above or below them, the 3dRadar should be used. Otherwise, the 2dRadar should be used. The player can also manually trigger the 2dRadar or 3dRadar by hitting one of two buttons reserved for the two radar operations. ++ Three Flight Instruments: Compass, PitchMeter and RollMeter The Engine has three flight instuments as well. They are used to tell the player about their DirectionFacing (Yaw), their climbing or descent (Pitch) angle and their Roll angle. These three instruments are triggered by the following commands: Compass, PitchMeter and RollMeter. ++ Three Defensive Instruments: AttackAngleMeter, AttackPitchMeter and CheckMissileLock The Engine has three defensive instuments too. They'll say at what angle the player is, as seen by the attacker. If the attacker is headed straight at the player, both angles are zero. The AttackAngleMeter is similar to AngleOnTheBow for submarines. The AttackPitchMeter is the vertical equivalent of that. Check MissileLock is used to see if the attacker is aimed within a degree of the player. These three instruments are triggered by the following commands: AttackAngleMeter, AttackPitchMeter and CheckMissileLock. The radar and instruments use both midi sound and speech to communicate quickly such vital information to the player in real time. ++ More choice for Radar and Instruments: In addition to the two radar buttons, there are three buttons the player can hit to trigger three instruments: Compass, PitchMeter and Roll Meter. These instruments deliver quick directional midi indications as well as spoken details. The speech can be interrupted by any other speech. They are normally triggered by the player, but you can also trigger them by issuing these three commands: 2dRadar (gives one iteration of the 2D radar system) 3dRadar (gives one iteration of the 3D radar system) Compass (gives one reading of the compass) PitchMeter (gives one reading of the PitchMeter) RollMeter (gives one reading of the RollMeter) AttackAngleMeter (gives one reading of the AttackAngleMeter) AttackPitchMeter (gives one reading of the AttackPitchMeter) CheckMissileLock (gives one check to see if attacker has player in Missile Lock) The instruments should be used in code whenever the player changes the angle they are facing in any way. NOTE: the radars and instruments are made of functions, so you can reprogram them however you like. This will ease the transition into DirectX when the time comes, and make it easy to customize the whole feel of games. These instruments make use of certain extra commands and variables, and they store the latest inventory of "stuff out there" in a table that you can get to by using the following commands: + ResearchRadar (This causes the Engine update the "what's out there table".) The table consists of blip objects and their properties. The table is arranged from closest (to the player) to the furtheset (from the player). The table has one page for every object that's close enough to see. Each page is a blip. Whenever you grab a blip, it packs a series of variables from the blip page you requested. Here is how you grab a blip: First see how many blips there are, so you know when to stop grabbing them. + ^BlipCount (This tells you how many pages there are, one for every blip object.) Now grab each blip and deal with it one at a time. + GetBlip 99 (You can put any number, not just 99. Put the page number you want.) The preceding command has packed the following variables: + ^ThisBlipIndex (This is a reminder of what blip page you are on). + ^ThisBlipDistance (This is how far away the blip object is.) + ^ThisBlipDistancePercentage (This is the distance divided by visibility.) + ^ThisBlipCategory (This is the parent category of the blip object.) + ^ThisBlipName (This is the actual name of the blip object.) + ^ThisBlipIsRecognized (You are able to recognize this blip object.) + ^ThisBlipYaw (This is the angle on a map of the object from you.) + ^ThisBlipPitch (This is the vertical angle relative to the ground of the object to you.) + ^ThisBlipTopGroup (This is the main category like person, location, thing or tool.) + ^ThisBlipChasing (This is the extent to which the object is chasing you.) + ^ThisBlipRelativeAngle + ^ThisBlipRelativePitch + ^ThisBlipAttackAngle + ^ThisBlipAttackPitch + ^ThisBlipMissileLock + ^ThisBlipType The BlipType is a descriptive number that makes it easy to code radar readouts. Here are the numbers and what they stand for: 1: It is a "thing" or "other". 2: It is a location that you have access to. 3: It is a location that you do not have access to. 4: It is a tool that has you in missile lock. 5: It is a tool that is chasing you. 6: It is a tool that is not chasing you. 4: It is a person that has you in missile lock. 9: It is a person that is chasing you. 9: It is a person that is not chasing you. ++ Length, Width, Height Orientation, Shape and Radius. Now would be a good time to introduce some of the more exotic properties that every location can have. They have no meaning and are irrelevant unless you use the Move command, which will be covered soon. Shape is either "Round or Box". If the shape is round, the extent of a location is defined by the Radius and height. If the shape is Box then the extent of the location is defined by Length, Width, height and Orientation. If the orientation is zero then that means that the length is perfectly lined up with North and South. If the orientation is 90 then the length is perfectly lined up with East and West. For Radius or Length and Width, the MapAddress defines the center point. For height, the MapAddress defines the floor. Now it is possible to understand the three dimensional outline of a certain location, which can be shaped like a box or shaped like a round cake. ++ Player has his own MapAddress. Surprise! Every Person, thing and tool has its own MapAddress. Of course, the MapAddress is actually made of four properies: NorthSouth, EastWest, Altitude and AboveBelow. Altutide gets ignored and is set to zero most of the time anyway. AboveBelow is only significant if a location is given a height of more than zero. If height is zero it is assumed to mean as high as the sky. Normally you never notice the player's MapAddress, because it is always set to the MapAddress of whatever location it is at. A clever programmer could use it to advantage, though. Suppose two rooms are two different locations. The player could toss a gernade from one room into another. Its primary significant, though, is when the player moves around. While you can make a great game where the road from one town to another is a location and all the game playing is done by text, you can also get more jiggy with it, and have the player move themselves around by using keys as a joystick. (Perhaps some day an analog joystick, but one thing at a time!) This is where the concept of access really comes in handy. A location has a shape, and every point inside that shape is considered to be inside that location. Duh. Now if a player moves so that their MapAddress point gets inside a location's outline, then they are now officially at that location. ++ Access and collisions But what if there is a wall in between? You can control what location is allowed from another location by setting the access property of each of your locations. You can make it so the player cannot go through a wall, but they can have access to a location by using a pair of locations called doorways. Each door can have two doorways, one is inside the room, the other is on the other side. You can close and open the door by controlling the access property of each doorway. The doorway that faces the outdoors can have continual access to a location called Chicago, which has a shape of round and a radius of the city limits. When a player tries to leave the outline of a location, the Engine looks at the list of locations in the access property of the location they are trying to leave. Among those listed, only those that include the player's intended MapAddress point are considered. Of those, the one closest is the location the player will go to. If none are available, then the player will stop one foot short of where they tried to move, and bounce off with a loud thud. A variable called ^Impact is set to the player's speed, then the player's speed is set to zero. If the player tries to enter the outline of a location and the location is on the access list of the location he is trying to leave, he leaves the previous location and successfully enters the new location. If access is denied, he stops one foot short and there is Impact. This is how a world can be created so the player can move himself about within it. One other thing. If the player tries to enter the same point as another player, thing or tool, they stop one foot short and there is an impact. If the object is an inch tall it can be assumed the player tripped over the object and stopped. Height is of no consideration when it comes to collisions with other players, things and tools. (If a game author wants to go further they can create and tend properties like mass, and have the interaction be calculated as soon as the impact is set to a non zero number, but that's too geeky even for me.) + Outside What if the biggest location is Chicago and the player goes outside of it? There is one location that has no boundaries, and contains all other locations. It is called "Outside". ++ A Function called NewLocation When the player enters a location, a function called "NewLocation" is performed. If the game author wants to do anything about that event they can write code that checks to see what the name of the new location is, then does whatever is appropriate. An example of this would be if you are being chased by an eleven foot snake, and you know that if you can make it to a certain cave, you will be rescued by a thirty five foot mongoose. ++ A Function named after a Location Also, since entering the new location, recent monsters are left behind and the player is ready for the next challenges in the new location. Here is how you accommodate such. If a function exists by the same name as that location then that function will be performed automatically. If you want, you can have that function contain a ForceSituation command that will make the Engine drop everything it had been doing before and start the new situation. This is a good way of allowing the player to get themselves into situations. ++ The Move command (finally!) When a person moves, they move in the direction they are facing. So far we have a direction in which the player is facing, and some set boundaries to determine where the player is allowed to move. Actually moving the player is easy to do, but results in a really cool chain of events! Here is the move command: Move For ^TimeDuration at ^Speed. NOTE: The Move command ignores the "Pitch" property and does not allow flight. If you want to make the player fly, use the "Fly" command. It does all the same stuff as Move, but it also takes the Pitch property into account. Examples: Move For 6 seconds at -3 mph He is walking backwards at 3 miles per hour for the next six seconds. Move For 6 feet at -3 mph He walks backwards a distance of six feet at 3 miles per hour. Something wonderful happens when you move the player. The following chain of events happens: 1) The player tries to move as allowed by what I've described above. 2) The path of the player is anticipated. 3) The path of any wandering monster on patrol is anticipated. 4) Either access is allowed, access is stopped by an Impact, or the movement (and the time it takes to happen) is cut short by a wandering monster that crosses his path! 5) If the player catches the eye of a wandering monster, the monster might chase the player. Whether he gives chase or not depends on the visibility during that leg of his journey, the distance and his aggressiveness. Now matter how aggressive he he is, if the player is too far away he doesn't know the player is there and will not give chase. If he does see the player and his aggressiveness is greater than the distance he will give chase. In each of these chains of events, the monster moves toward the player just a little. By running these chains over and over again the action is kept moving. While a monster is giving chase, the player is still allowed to move no less than one second at a time, or else the player would never get anywhere. 6) After the monster has moved toward the player, if chase is being given then the Engine launches a Function called TheChaseIsOn. It is up to you to write that function. It will also launch a Function whose name starts with the word "Animate", follwed by the name of the monster. It is up to the game author to create this function. If you set the monster's aggressiveness equal to or less than the distance, the monster will wander off. If you set the aggressiveness to a negative value the monster runs away. If you wish, your game code can perform a radar operation after moving. Thus the chain of events is done. Simply by moving the player, you can trigger this chain of events within a loop structure in a function you have created to provide real time game play. So far we see that the monster gets a turn to do somthing to the player, but when does the player get to do something to the monster? Only moving advances the ^PretendTime clock, so your player can hit other keys than the joystick he uses for moving. In old games there is at least a "Fire" button to shoot a weapon. Since this is also a strategy and mystery Engine it goes a little deeper than that. You can write code to let the player load up their weapons under the letter keys of their choice! (That is the equivalent of training them to use them in combat without hesitation.) Here is how: ++ Chain of events without moving If you use StartPretendClock to leave the PretendTime clock running in real time, any monsters on the loose will continue to go about their travels. Because the engine can't spend all its time moving monsters little bits at a time, it will try to figure out how often to advance all the monster routes. Sometimes a player can sneak by when they would normally get chased, so there is some luck involved too. If the player was going through a text role playing situation and you left the PretendTime clock running, they might be trying to figure out how to open a door when suddenly a wandering monster could start chasing them. When this happens, the Engine launches a function called TheChaseIsOn. You can use that function to launch your own function that contains an action loop. In this way some unpredictable events can launch a fast paced action scene right in the middle of a mystery. ++ Fly This is the same as move, but unlike Move, this will take into account the Pitch property, allowing flight. Just like Move, Fly initiates the chain of events. Examples: Fly For 6 seconds at 40 mph He is flying at 40 miles per hour for the next six seconds. Fly For 600 feet at 40 mph He flies a distance of 600 feet at 40 miles per hour. For both Move and Fly, the speed is known. Either the distance or the time is figured out based upon the direction the person is facing, and whether they are flying. +++ Commands to move and turn in any way immaginable: The following two commands also initiate the chain of events. They move the person in three dimensions. The speed and distance is calculated, based upon X, Y and Z as well as what we mean by X, Y and Z. If PersonalXYZ is chosen, X is the person's left to right, Y is the person's up and down, and Z is the person's ahead and behind. If GlobalXYZ is chosen, X is EastWest, Y is AboveBelow and Z is NorthSouth. ++ MoveGlobalXYZ Within 6 seconds, X = 1, Y = 22, Z = 4 ++ MovePersonalXYZ Within 6 seconds, X = 1, Y = 22, Z = 4 ++++ Having a real Attitude Attitude is the word used to describe the direction an aircraft is pointing in. There are three ways you can rotate a craft to change its attitude. ++ Pitch, Yaw and Roll These three properties represent three different ways you can turn something like a jet. The following commmands makes 3D ariel dogfights possible. The only way to tone down the geekiness of this is to simply learn the terms. Yaw is Left to Right. Pitch is climb or dive. Roll is the spin on an arrow or the turning of a screw. You can either change the values of these properties in relative amounts or set them in an absolute sense. + Pitch Pitch was covered above. It is the aspect of your orientation that determines whether you are climbing or diving. + Yaw is the same thing as DirectionFacing When a car is turning, it is changing in Yaw. It is the exact same thing as "DirectionFacing". You can use either term. It pertains to north, south, east and west. + Roll If you've ever heard the expression "Don't rock the boat", then you've thought about Roll at least in a subtle way. The most common way to rock the boat is from side to side. When that happens, the boat's attitude is changing in the aspect called Roll. ++ TurnPYR 0, 0, 5 This makes relative differences to the way the player is facing. The example given would make the roll 5 more degrees than it already is. You can replace the numbers with variables. For example: TurnPYR 0, 0, ^MoreRoll ++ FacePYR ^P, ^Y, ^R This sets the direction the player is facing in an absolute sense. Its result is as if you had first set P, Y and R all to zero, then called TurnPYR with the same numbers. Here are some examples: FacePYR ^P, ^Y, ^R FacePYR same, same, 5 The second example given uses the word "same". For whatever you use the word "same", it keeps the values you already had, allowing you to specify a new value for just one setting, in an absolute sense. ++ Steering in the air Suppose you are facing straight up, and you want to turn to the left. This is something that could happen in flight. Since you already have a command for "Turn", and since the word "steer" implies turning in a more personal sense, we will use "SteerXYR" for in flight steering to the left or right and up or down, as well as rolling over like a spinning arrow. SteerXYR ^ChangeForX, ^ChangeForY, ^ChangeForPersonalRoll If you are flying right side up and you say SteerXYR 270, 0, 0 then that will turn your course left by 90 degrees. People outside of your plane would agree that you are turning left. If you were heading north then now you are heading west. But what if you are flying upside down? Then in that case, everyone outside your plane will say you are turning right, unless they are standing on their heads, because you were heading north and now you are heading east. That is how steering is like turning but in a more persnal sense. For the sake of simplicity, it is assumed that turning takes no pretend time. Remember these commands are issued within a loop, so you can keep doing a little more each time around the loop. In this way you can simulate velocity and acceleration. Since the player will have to use the cockpit instruments and radar to determine how they are facing, where they are going, what is where nearby and who is firing upon them, as well as which way is up, you will need to give them enough time while playing to check all this stuff. It is a delicate balance between providing a fast paced game and making them feel overwhelmed. Therefore, a useful technique would be a time distortion in the heat of battle. Many movies have used this technique to clearly show action that takes place within a very brief period of time. You can also use this technique to give the player time to consult the instruments and radar, as well as to think through the movements required. It is up to you to provide the relationship between pretend time and real time. The way you can do this is by using shorter or longer pauses in your loop, as well as providing larger or smaller turns and movements each time around the loop. The game Engine thinks only in a full three dimensions, not two, but you can set it up to provide an old fashioned arcade style two dimensional experience if you like, simply by setting the value of Z to the same for everything and adjusting all turns and moves and facings accordingly. +++ Momentum and acceleration In walking about, the movement directly results from the player's keystroke. To transform that into a velocity and acceleration implementation, you can have your own three variables for motion, ^DeltaX, ^DeltaY and ^DeltaZ. Then you can add the player's input into the value of those, and then apply the accumulated result to the motion to be commanded. No fancy math; it's all addition. The result is that you allow the player to build or reverse momentum. That works nicely for absolute XYZ movements, but what about those cool commands that let the player turn, face, steer and move? You can let the Engine keep track of the momentum for you. To do that you need to turn the momentum feature on. You can turn it off at any time, which immediately places the player at rest (non-moving). (When there is a collision, the Engine turns it off then on again, if it was on.) Here is how you turn it on and off: + Momentum On (turns on player's ability to accumulate momentum) + Momentum Off (turns off player's ability to accumulate momentum) After every move the Engine will pack three properties of the player: LastMoveEastWestRate LastMoveAboveBelowRate LastMoveNorthSouthRate NOTE: When momentum is on, if you say "Move Player for Distance @ speed" then the player spends the same amount of time traveling as otherwise, but has a combined distance. +++ Aiming and firing a weapon Weapons are tools. Tools, like people, have the properties of 3D navigation. This lets you throw them and aim them. To aim them, you set their orientation just as you would an aircraft or car. If you want to automatically aim the weapon at the enemy, you can issue this command: ^AimX and ^AimY These variables are in degrees. They are angles added to the direction the player is facing when the player fires a weapon. They are personal, from the point of view of the player. If you want to allow the player to aim a weapon any direction other than straight ahead, you can set these variables to whatever you like, based upon player action you have captured from the keyboard. + Aim Aim ToolName at EnemyName (This almost makes it too easy, but some time you may need it.) The aim command changes the ^Aim X and ^AimY variables so that the weapon points to the enemy that is named. When a verb is used, a function by the same name as the verb is called, if the function has been created. In that verb function you can test to see if the weapon makes contact with the enemy by using a command called Fire. It sounds silly to Fire a sword, but there has to be just one word used in all cases, so I chose the word Fire. + Fire When you fire a weapon, the Engine makes a list of every person and tool that is aimed at by the weapon, and that is in range. Of those, the closest is what gets hit. The Engine packs a variable for the name of the tool or person that got hit, and the also packs a variable that tells if the weapon hit or missed any target. You can issue the command by itself, in which case the range is determined by the range property of the weapon, or else you can specity a temporary range for just this attack. Examples: Fire crossbow Fire crossbow 30 feet + ^Missed This is set to "False", or "True", depending on whether the weapon hit a target. + ^WhoGotHit This contains the name of the tool or person that got hit. If no tool or person got hit but the weapon entered into a location, this variable contains the name of that location. If the weapon did not enter into a new location then this variable contains the name of the location where the weapon strike originated. + ^HitDistance If your weapon struck something, this variable tells how far away from you it is. ++ PackLetterPower and ^LettersSpokenFor First, pack the system variable ^LettersSpokenFor with every letter already in use, (like your joystick keys, for instance). Suppose your joystick letters are I, J, K and M. Then you put: ^LettersSpokenFor = "IJKM" Then you issue the command: PackLetterPower The Engine then leads the player through a dialog to pack a letter of their choice with a verb or power of their choice if they really have the power to do it. What determines whether they can add the power is if it is a GoodAction. If they succeed in packing a letter with a verb or power, then the Engine adds that letter to the list of spoken-for letters. The engine finds out if your Power is a kind of weapon. Then the Engine creates a function by the name of the letter. It fills the function with a few lines. Suppose the letter was A and the power was "StartFlying". The Engine would do the same thing as if you had put: CreateFunction A PerformFunction StartFlying End Function While this is not very violent it could get the player away from the monster. (Of course, you would have to write that function called StartFlying). Suppose the letter was B and the power was "shoot". In this case the player has told the Engine that this power is a kind of weapon. The Engine would do the same thing as if you had put: CreateFunction B Equation: ^PowerName = "shoot" PerformFunction UseWeapon End Function The Engine also creates the following function if it has not already done so: Create Function UseWeapon If GoodAction ^PowerName Then Fire ^WeaponUsed If ^Missed = "True" Then ^GotHit = "False" Otherwise ^GotHit = "True" Equation: ^^FullAction = ^PowerName ^WhoGotHit If GoodAction ^^FullAction Then ^GotDamaged = "True" Equation: ^TempStamina = SoCalled^WhoGotHit's_Stamnina - ^MaxDamage Equation: SoCalled^WhoGotHit's_Stamina = ^TempStamina Else ^GotDamaged = "False" End If End If End If End Function Whenever that function called B is performed, the Engine ends up calling the Function called Shoot, because Shoot is the name of the weapon power. It is your job to fill the function called Shoot with instructions to make a certain type of gun sound. You notice that there is a system variable called ^MaxDamage. That was packed when the Engine checked to see if Shoot was a GoodAction. Every tool that could enable the player to shoot was searched for a Damage property. The highest value found was put into the ^MaxDamage variable. When that happened, the name of the weapon used was put into the ^WeaponUsed variable. When the UseWeapon Function sent the Fire command, the Engine looked up the weapon used to get its range. If it had the range and the aim was good, then the shot was successful. As you can probably tell, the results from this function are variables called: ^GotHit ^GotDamaged ^MaxDamage ^WeaponUsed If the target got hit and the action was allowed, then the target took a loss in stamina to the extent of the variable called ^MaxDamage. Also, the weapon that did the damage is identified by the variable ^WeaponUsed. You can then make noises, speak to the player or otherwise let them know what just happened. Now whenever the player types a letter, the game code can say: Choice Variable ^^PlayerLetterTyped When I When J When K When M When Else DoFunction SoCalled^^PlayerLetterTyped End Choice (I did not bother to fill in the joystick when lines, but you can.) ++ You can already Pack a Letter with a Power! Suppose you want to pack a "shoot em up" type fire button with a power, with no help from the player? You can already do that by issuing one of these two sets of lines: Here is the first version. It allows the letter A to launch a verb function called fly: CreateFunction A PerformFunction fly End Function Here is the second version. It allows the letter A to launch the UseWeapon function, with "shoot" as the power being used: CreateFunction A Equation: ^PowerName = "shoot" PerformFunction UseWeapon End Function +++ My Monster has a Paper Route! Remember the concept of the wandering monster? What determines how he wanders about? You do! You can give your monster a route, just like a paper route. A paper route may be defined by the houses he goes to along the way, but it is more than that. A paper route also consists of the journey between, from one house to the next. In the same way, you can define a whole journey for your monster by specifying a few legs of the journey. Therefore, a route consists of a series of legs. When the last leg is performed, your monster will do the whole route over again until you tell him to stop. To tell the monster to stop doing the route, you set his Route name to "none". Here is how you create a route: Create Route RouteName Location: LocationName (Every Route takes place within a certain location.) ChaseDistance: 3 feet (always in feet; the closest someone giving chase will get.) Leg Put any number of equations you want to in here. Visibility: 100 feet (always in feet) DestinationType: Place (or else Distance) NorthSouth: 1 miles; 3 feet EastWest: 20 miles; 500 feet Speed: 30 mph (you can say mph, it's converted and remembered as feet per second.) Leg Put any number of equations you want to in here. Visibility: 100 feet (always in feet) DestinationType: Distance (or else Place) NorthSouth: 21 miles; 30 feet EastWest: 2 miles; 50 feet Speed: 30 mph (you can say mph, it's converted and remembered as feet per second.) Leg Put any number of equations you want to in here. Visibility: 100 feet (always in feet) DestinationType: Distance (or else Place) NorthSouth: -1 miles; -3 feet EastWest: -20 miles; -500 feet Speed: 30 mph (you can say mph, it's converted and remembered as feet per second.) End Route NOTE: When the Engine performs a route leg, it packs a variable called ^ThisMonsterName. You can have your equations look up the monster name and his peoperties, so that you can do some complex things like write code to constantly improvise new routes. Set MonsterName Route: RouteName Assigning a route to a monster is actually a process of cloneing the route. Every person and tool actually has their own private, personal route. When you set their route property to the name of a route, the person (or Monster) is actually copying that route to their own private, personal route. The moment you set the route, that monster is activated and will begin his patrol. This defines your monster's route. In this case, the monster starts at a fixed MapAddress, then goes a relative distanced, then goes another relative distance. When the cycle repeats, the monster goes back to the first fixed MapAddress again. Normally your monster will give up the chase as soon as he finds that he is not in the same location as the player. This is because chase can only be given by a monster in the same location as his prey. If you want your monster to continue the chase in a new location where the player has gone, you will need to give him a Route that takes place at the new location. You can do that within the function called NewLocation that was described above (or within a function by the same name as the new situation). When you create a route for a monster, you need to take care not to have his route go through walls and things like that unless he is a ghost. So plan ahead, because that is up to you. At the start of each leg of his route, the monster checks to make sure the destination doesn't place him in a new location. If it would, he'll skip that leg entirely and go on to the next leg. Monsters are not courageous, just surly. In case you ever want to change the definition of the route in the middle of a game, you can refer to any line in each of its legs as a function line. Here is the Syntax: ^A = Route~ManicTourForTaz~Leg2#3 The above example has just filled the variable ^A with the third line of the second leg of the route called ManicTourForTaz. That is for people that like to create self programing programs. ++ Updating information on Routes, Monsters and Objects and Bordering Locations: Knowing when the Engine takes stock of things can help you keep it up to date when you change certain things mid stream. Rather than the Engine always checking everything every minute like Bart saying "are we there yet" a million times, there are certain key times when the Engine does an inventory of Monsters and Objects and Bordering Locations. Those times make sense and it's simple to use them. + When you reach a new Location: The location containing the player is reflected in a variable called ^ThisLocation Whenever ^ThisLocation changes, the Engine takes inventory of every Route, Monster and Object in the location, so it can prepare to think about collisions and attacks. + When something's Route or Location propertys change When either the route or the location property of something changes, the Engine updates the location's inventory regarding just that particular something. ++ Positioning the player at the center point of a new location: There are two ways to reach a new location. One is by moving the player in physical space. The other is by entering a new situation and the situation contains a Location: command that sets a new location. When a player moves in physical space to reach a new location, he has moved his position to be within the new location so everything is fine. But what if a new situation changes the location? Well, in that case the Engine will automatically place the player at the center point of the new location. +++ Movie Ratings for Games: One last word: Fantasy Gaming, aka Interactive Fiction, is supposed to be a safe diversion from the worries and trials of our difficult lives. Please keep it safe by avoiding things that would traumatize others or cause them to stumble. If you know that your game would not be appreciated at church, please give your game an honest movie rating and make it known. That way, end users will have no excuse to write annoying things to you about it. Therefore, there is one more thing to go into the files: Rating: RatingLetters Reason. Examples: Rating: G for General Audiences. Rating: PG13 for Violence and strong language. Rating: NGB for Nerdlike, Geeky Behavior.