; ----------------------------------------------------
;                  actions.txt file
; ----------------------------------------------------

; this is where all the ROUTINES live. 
; they can be called by ROOMs, OJBECTS and VERBS in the adventure.txt file

; each routine begins with a < and ends with a > 
; with the declaration line <ROUTINE and then the name of the routine being the first line
; the routine name must be exactly as it appears in the matching ROOM, OBJECT or VERB's
; (ACTION ...) sub entry. ; eg, <ROUTINE CLOSE_ROUTINE

; the > at the end of the routine can append the final line of the routine, or it can be
; on its own after a carriage return at the end of the routine (can help reading when long
; lines push the > off the right hand edge of the screen.

; then each sub-entry for that routine follows. Each must be enclosed in normal brackets ( )
; an entry can go on for one or more lines, but it must begin with ( and end with )

; ----------------------------------------------------
; valid sub-entries for a ROUTINE
; ----------------------------------------------------

; an entry can be one of the following:

; - a call to another routine (ROUTINE ANOTHER_ROUTINE)
;   in this case, ANOTHER_ROUTINE must be a valid routine in the actions.txt file
;   note that the called routine could pass, and the rest of this routine won't run
;
; - a condition (IF condition THEN actions)
;
; - an action - these are all currently implemented actions available in ZILish:

;   SETTIMER, SETFLAG, UNSETFLAG, SETROOM, TELL, INC.CARRIED, DEC.CARRIED,
;   SHOW_INVENTORY, REDESCRIBE, INC.SCORE, DEC.SCORE, ENDGAME
;
; a condition must begin with (IF and a space, then one or more things to check to see if 
; they're true or false. If there is more than one test, each test must be separated with either 
; an AND or OR.

; LIMITATION NOTE - the tests are done left to right and you *can't* bracket tests
; eg (IF (x AND b) OR c ... *won't work!!!*
; you can mix and match ANDs and ORs on a single IF line, but you might get unexpected results.
; put ORs at the start, and then add AND. it will behave like IF (x OR b) AND c
; if necessary, split more complicated tests down into separate IF conditions.
; this sometimes means repeating yourself. Sorry about that.

; after the test(s) there must be a THEN after which follows the actions the parser must do when
; the test(s) have passed.

; note there MUST NOT BE ANY SPACES!!! either side of the "=" or "<>" - at best the parser will
; throw a syntax error, at worst it'll hang.

; ----------------------------------------------------
; examples of valid tests
; ----------------------------------------------------

; (IF VERB=... if player has typed the verb... (must be followed by a valid verb to check)
;
; (IF OBJECT=... if player has typed the object... (must be followed by a valid object to check)

; (IF INDIRECT=... if player has included the indirect obect ... (must be followed by a valid
;                  object to check). Note that if a player's input contains only one recognised
;                  OBJECT, that object is the direct object. There can only be an INDIRECT 
;                  if the parser recognises a second OBJECT in the input string. The first object
;                  to appear in the string is the direct object (OBJECT) and the second object to
;                  appear in the string is the INDIRECT.

; (IF SCORE=...    if the player's score has achieved a certain value

; (IF ROOM.PLAYER=... if the player is currently in room...
; (IF ROOM.THIS=... if the object the player entered is currently in room ...
; (IF ROOM.XXX=... if the object specified is currently in room ... XXX must be a valid object.

; Note you can also check for inequalities in room - (IF ROOM.XXX<> ...
;
; an OBJECT's ROOM value must be a valid ROOM, or it can have the value NONE, which means it 
; doesn't physically exist in the game - can't be picked up, carried etc, but the parser will
; still process it. an object can also have a valid room value CARRIED, this means the player is
; carrying that object.
; it should go without saying, but the PLAYER can *never* have the ROOM value NONE or CARRIED.

; (IF TIMER=...     - if the timer set by SETTIMER (see below) has reached a value
;                     valid values are 1 - 99
; (IF TIMER<> ...   - if the timer set by SETTIMER (see below) does not equal a particular value
;                     can be used to check if something hasn't timed out yet (IF TIMER<>0 THEN...)
; (IF GAMETURN= ... - if a specified number of turns have elapsed since the game began
; (IF GAMETURN> ... - if more than a specified number of turns have elapsed since the game began
; (IF GAMETURN< ... - if less than a specified number of turns have elapsed since the game began

; testing flags: note that there is no equality (=) or inequality (<>) in testing flags.
; the two tests IF FLAGSET and IF FLAGUNSET do the job of = and <>
; for example, if you wanted to test if the OPEN flag was NOT set for a particular object, you
; would write (IF FLAGUNSET.THIS OPEN ....

; (IF FLAGSET.THIS XYZ if the OBJECT typed in by the player has the XYZ flag set
; (IF FLAGSET.OBJ/ROOM XYZ if the OBJECT or ROOM specified has the XYZ flag set

; (IF FLAGUNSET.THIS XYZ if the OBJECT typed in by the player does not have the XYZ flag set
; (IF FLAGUNSET.OBJ/ROOM XYZ if the OBJECT or ROOM specified does not have the XYZ flag set

; (IF EXCEEDCARRY if the SIZE of the object typed in PLUS the current carried SIZE 
; is greater than player's max carry

; In routines that deal with two objects, .THIS references the main object and
; .INDIRECT references the indirect object. 

;     "switch light on" - this has a verb ("switch") and two objects:
;     "light" is the  .THIS object, and "on" is the .INDIRECT object.
;     NOTE: order of objects matters!
;     using the sample ROUTINES below, if the player typed in "switch on light", 
;     the parser would return SWITCH as the verb,
;     "on" as the .THIS object, and "light" as the .INDIRECT object.
;
;     "tie rope to pole" - VERB is "tie" ; .THIS is "rope" ; .INDIRECT is "pole"
;     "tie pole to rope" - VERB is "tie" ; .THIS is "pole" ; .INDIRECT is "rope"

; EXAMPLES OF ACTIONS:
; --------------------
; SETFLAG.THIS XYZ - sets specified "XYZ" flag for the object typed in
; SETFLAG.anyOBJ/ROOM XYZ - sets specified "XYZ" flag for a specified object or room

; UNSETFLAG.THIS XYZ - unsets specified "XYZ" flag for the object typed in by player
; UNSETFLAG.TRAPDOOR XYZ - unsets specified "XYZ" flag for a specified object / room

; SETROOM.THIS ROOMXYZ   - sets the location of the object typed in by the player
; SETROOM.anyOBJ ROOMXYZ - sets the location of a specified OBJECT (mustn't be a door object)
;                          ROOMXYZ must be a valid ROOM or ROOM.PLAYER. Setting an object location
;                          to CARRIED moves the item into the player's inventory

; SETTIMER=50 - sets an ingame timer to start counting down turns from the number specified
;               every time the player enters a command, the counter counts down by 1
;               valid values are anything from 1 to 99

; INC.CARRIED SIZE.THIS - increases the amount the player is carrying by the SIZE of the object typed in
; DEC.CARRIED SIZE.THIS - decreases the amount the player is carrying by the SIZE of the object typed in

; INC.SCORE xyz - increases the player's score by xyz (must be a number)

; SHOWSCORE - displays the player's current score

; ENDGAME - the game breaks out and terminates immediately on seeing this action.

; ~not implemented yet SETSIZE.THIS - sets the size value of the object typed in by player - must be followed by a numerical value
; ~not implemented yet SETSIZE.LAMP - sets the size value of a specified object - must be followed by a numerical value
;
; ~not implemented yet: MAXCARRY - sets the maximum amount the player can carry - must be followed by a numerical value)
;
; ~not implemented yet: DEC.SCORE 000
;
; TELL "Words words words." - this puts the words up on screen
; you can optionally include the "%" character and the parser will replace it with the 
; object that the player has typed in. 
;
; ADDITIONAL NOTES
; there can be more than one assignment after the THEN
; there is only one pair of brackets around the whole condition:
;   (IF test AND test THEN
;      action
;      action
;      action)
; the last action must be terminated by a close bracket ) 
; then the next condition must begin again with an open bracket
; as mentioned at the top of this file, once all the sub-items for a routine are done,
; the whole routine must be closed with a greater than sign >
;
; for VERB and OBJECT ROUTINES, the first (IF ....) test to succeed will be run by the parser,
; all the following (IFs..) in that routine will NOT be executed, so the order of the (IF...)
; conditions matters!!!
; EXCEPT - in ROOM routines, the parser WILL execute ALL the sub-entries, even after one or more
; have successfully executed




; -----------------SAMPLE CODE STARTS HERE-------------------


<ROUTINE GLOBAL
  (IF TIMER<>0 AND ROOM.CLOCK=ROOM.PLAYER THEN
    TELL "You can hear a faint ticking sound.")
  (IF TIMER<>0 AND ROOM.CLOCK=CARRIED THEN
    TELL "You can hear a faint ticking sound.")

  (IF ROOM.LANTERN=ROOM.PLAYER OR ROOM.LANTERN=CARRIED AND FLAGSET.LANTERN LIT THEN
    TELL "The lantern is giving off a steady, pale glow.")

  (IF GAMETURN=4 THEN
    TELL "If you'd like me describe where you are again, just type in 'look'.")
  (IF GAMETURN=8 THEN
    TELL "If you'd like me to look at something in more detail, just type 'examine' and then the thing you'd like examining.")
>

<ROUTINE LIVING_ROOM_ROUTINE
  (IF FLAGSET.TRAPDOOR OPEN THEN
    TELL "The rug is folded back revealing an open trapdoor in the middle of the floor. A rusty ladder leads down into the darkness.")
  (IF FLAGSET.PERSIAN_RUG LIFTED AND FLAGUNSET.TRAPDOOR OPEN THEN
    TELL "The rug is folded back revealing a trapdoor in the middle of the floor.")
  (IF FLAGSET.LIVING_ROOM CYCLOPS_GONE THEN
    TELL "The door to the west has been ripped off its hinges and there is no sign of the cyclops.")
  (IF FLAGUNSET.LIVING_ROOM CYCLOPS_GONE THEN
    TELL "There is a menacing looking cyclops guarding the door to the west. It glares at you.")
>

<ROUTINE BASEMENT_ROUTINE
  (IF FLAGSET.LANTERN LIT AND ROOM.LANTERN=CARRIED THEN
    TELL "There is a sign on the wall that you can read in the dim light from the lantern. It says 'congratulations! you have finished the demo adventure!'"
    INC.SCORE 10
    SHOWSCORE
    ENDGAME)
  (IF ROOM.LANTERN<>ROOM.PLAYER AND ROOM.LANTERN<>CARRIED THEN
    TELL "It is very dark. You can barely see anything. Perhaps you should seek out some way of illuminating the room?")
  (IF FLAGUNSET.LANTERN LIT AND ROOM.LANTERN=CARRIED THEN
    TELL "It is very dark. You can barely see anything. I do believe you are carrying a lantern - perhaps you could switch it on?")
>

<ROUTINE KITCHEN_ROUTINE
  (IF FLAGSET.CUPBOARD OPEN THEN
    TELL "The cupboard door is open wide.")
>

<ROUTINE CLOCK_ROUTINE
  (IF VERB=WIND AND ROOM.CLOCK=ROOM.PLAYER THEN
    SETTIMER=5
    TELL "You turn the little key in the back round and around until it won't turn any more.")
  (IF VERB=WIND AND ROOM.CLOCK=CARRIED THEN
    SETTIMER=5
    TELL "You turn the little key in the back round and around until it won't turn any more.")
>

<ROUTINE PERSIAN_RUG_ROUTINE
  (IF ROOM.THIS<>ROOM.PLAYER THEN
    TELL "What rug?")
  (IF VERB=LIFT AND FLAGSET.THIS LIFTED THEN
    TELL "You lift the rug again and move it around a bit as best as you can. The trapdoor is still visible.")
  (IF VERB=LIFT THEN
    TELL "You heave at the corner of the rug, and manage to lift a corner back. You see a trapdoor revealed underneath the rug!"
    SETFLAG.THIS LIFTED)
>

<ROUTINE CYCLOPS_ROUTINE
  (IF VERB=FIGHT AND ROOM.PLAYER=LIVING_ROOM THEN
    TELL "REALLY? Are you completely mental? Sorry, I'm not going to let you do that. You wouldn't last 5 seconds!")
  (IF ROOM.PLAYER=LIVING_ROOM THEN
    TELL "Probably best not to mess with the cyclops. It looks like it's ready for a fight.")
>

<ROUTINE GET_ROUTINE
  (IF OBJECT=NULL THEN
    (TELL "I don't understand what you want me to get.")
  (IF ROOM.THIS=CARRIED THEN
    (TELL "But you're already carrying it.")
  (IF SIZE.THIS=100 THEN
    TELL "I can't pick that up.")
  (IF EXCEEDCARRY THEN
    TELL "You can't pick it up, you are encumbered. You could try dropping some other things first.")
  (IF ROOM.THIS=ROOM.PLAYER THEN 
    TELL "You pick up the %."
    SETROOM.THIS=CARRIED
    INC.CARRIED SIZE.THIS
    SETFLAG.THIS REMOVED)
>

<ROUTINE DROP_ROUTINE
  (IF ROOM.THIS<>CARRIED THEN
     TELL "But you're not carrying the %.")
  (TELL "You drop the %."
    SETROOM.THIS=ROOM.PLAYER
    DEC.CARRIED SIZE.THIS)
>

<ROUTINE CUPBOARD_ROUTINE
  (IF VERB=OPEN AND FLAGUNSET.THIS=LOCKED AND FLAGUNSET.THIS=OPEN AND ROOM.NOTE=NONE THEN
    TELL "You swing the doors open wide, and on the otherwise bare shelves, you notice a little note inside."
    SETROOM.NOTE=KITCHEN
    SETFLAG.THIS=OPEN
    INC.SCORE 10
    SHOWSCORE)
  (ROUTINE OPEN_CLOSE_ROUTINE)
  (IF VERB=LOCK AND ROOM.IRON_KEY<>CARRIED THEN
    TELL "But you're not carrying the cupboard door key.")
  (IF VERB=LOCK AND FLAGSET.THIS OPEN THEN
    TELL "You gently close the cupboard door, and twist the decorative iron key in the lock. It clunks satisfyingly."
    UNSETFLAG.THIS OPEN
    SETFLAG.THIS LOCKED)
  (IF VERB=LOCK AND FLAGSET.THIS LOCKED THEN
    TELL "The key won't turn. It must be locked already.")
  (IF VERB=LOCK THEN
    TELL "You twist the decorative iron key in the lock. It clunks satisfyingly."
    SETFLAG.THIS LOCKED)

  (IF VERB=UNLOCK AND ROOM.IRON_KEY<>CARRIED THEN
    TELL "But you're not carrying the cupboard door key.")
  (IF VERB=UNLOCK AND FLAGSET.THIS OPEN THEN
    TELL "But the cupboard is already open.")
  (IF VERB=UNLOCK AND FLAGUNSET.THIS LOCKED THEN
    TELL "But the cupboard is already unlocked.")
  (IF VERB=UNLOCK THEN
    TELL "You twist the decorative iron key in the lock. It clunks satisfyingly."
    UNSETFLAG.THIS LOCKED)>    


<ROUTINE TRAPDOOR_ROUTINE
  (IF FLAGUNSET.PERSIAN_RUG LIFTED THEN
    TELL "What trapdoor?")
  (ROUTINE OPEN_CLOSE_ROUTINE)
  (IF VERB=LOCK AND ROOM.TRAPDOOR_KEY<>CARRIED THEN
     TELL "But you're not carrying the trapdoor key.")
  (IF VERB=LOCK AND FLAGSET.THIS OPEN THEN
     TELL "You swing the trapdoor closed, and twist the key in the lock. It clunks satisfyingly."
     UNSETFLAG.THIS OPEN
     SETFLAG.THIS LOCKED)
  (IF VERB=LOCK AND FLAGSET.THIS LOCKED THEN
     TELL "The key won't turn. It must be locked already.")
  (IF VERB=LOCK THEN
     TELL "You twist the key in the lock. It clunks satisfyingly."
     SETFLAG.THIS LOCKED)

  (IF VERB=UNLOCK AND ROOM.TRAPDOOR_KEY<>CARRIED THEN
     TELL "But you're not carrying the trapdoor key.")
  (IF VERB=UNLOCK AND FLAGSET.THIS OPEN THEN
     TELL "But it's already open.")
  (IF VERB=UNLOCK AND FLAGUNSET.THIS LOCKED THEN
     TELL "But it's already unlocked.")
  (IF VERB=UNLOCK THEN
     TELL "You twist the key in the lock. It clunks satisfyingly."
     UNSETFLAG.THIS LOCKED)
>


<ROUTINE OPEN_CLOSE_ROUTINE
  (IF VERB=LIFT OR VERB=OPEN AND FLAGSET.THIS LOCKED THEN
    TELL "It won't open - if must be locked.")
  (IF VERB=OPEN OR VERB=LIFT AND FLAGSET.THIS OPEN THEN
    TELL "It is already open.")
  (IF VERB=OPEN OR VERB=LIFT THEN
    TELL "You open the %."
    SETFLAG.THIS OPEN)

  (IF VERB=CLOSE AND FLAGSET.THIS OPEN THEN
    UNSETFLAG.THIS OPEN
    TELL "You close the %.")
  (IF VERB=CLOSE THEN
    TELL "The % is already closed.")
>


<ROUTINE OPEN_ROUTINE
  (IF OBJECT=NULL THEN
    TELL "I don't know how to open that.")
  (TELL "I don't know how to open a %.")
>

<ROUTINE CLOSE_ROUTINE
  (IF OBJECT=NULL THEN
    TELL "I don't know how to close that.")
  (TELL "I don't know how to close a %.")
>

<ROUTINE INVENTORY_ROUTINE
  (SHOW_INVENTORY)>

<ROUTINE LANTERN_ROUTINE
  (IF VERB=SWITCH AND INDIRECT=ON AND FLAGSET.THIS LIT THEN
    TELL "The % is already lit.")
  (IF VERB=SWITCH AND INDIRECT=ON THEN
    SETFLAG.THIS LIT
    TELL "You switch the % on. It glows with a steady, but pale light.")
  (IF VERB=SWITCH AND INDIRECT=OFF AND FLAGUNSET.THIS LIT THEN
    TELL "The % is already off.")
  (IF VERB=SWITCH AND INDIRECT=OFF THEN
    TELL "You switch the % off."
    UNSETFLAG.THIS LIT)
>

<ROUTINE SAY_ROUTINE
  (IF OBJECT=PLUGH AND ROOM.PLAYER=LIVING_ROOM AND FLAGUNSET.LIVING_ROOM CYCLOPS_GONE THEN
    SETFLAG.LIVING_ROOM CYCLOPS_GONE
    TELL "Looking the cyclops in the eye, you utter the word 'plugh'. The cyclops cries out in mortal fear, and turns around, rips the door behind it from its hinges and legs it into the passage beyond."
    INC.SCORE 10
    SHOWSCORE)
  (TELL "You say 'plugh'. Nothing happens.")
>

<ROUTINE LOOK_ROUTINE
  (REDESCRIBE)>


<ROUTINE LIFT_ROUTINE
  (TELL "I'm not sure how to lift that.")>  


<ROUTINE NOTE_ROUTINE
  (IF VERB=READ OR VERB=EXAMINE AND ROOM.THIS=CARRIED THEN
    TELL "Written in a scribbled handwriting, the note bears the words 'the cyclops is terrified of the word plugh.'")
  (IF VERB=READ OR VERB=EXAMINE AND ROOM.THIS=ROOM.PLAYER THEN
    TELL "Written in a scribbled handwriting, the note bears the words 'the cyclops is terrified of the word plugh.'")
>

<ROUTINE EXAMINE_ROUTINE
  (IF OBJECT=CYCLOPS THEN
    TELL "The cyclops is about 10 feet tall. He stoops slightly to stop his head hitting the ceiling."
    TELL "Apart from the occasional grunt, he says nothing and does nothing. He watches you intently."
    TELL "He stands right up against the wooden door to the west, preventing anyone from opening it.")

  (IF OBJECT=CUPBOARD THEN
    TELL "It is a sturdy wooden cabinet, with solid wooden doors. There is a large keyhole in one of the doors.")

  (IF OBJECT=DEBRIS THEN
    SETROOM.TRAPDOOR_KEY=STRANGE_PASSAGE
    TELL "Lying hidden amongst the debris, you notice a small, rusty key."
    INC.SCORE 10
    SHOWSCORE)

  (IF OBJECT=TRAPDOOR AND FLAGUNSET.PERSIAN_RUG LIFTED THEN
    TELL "I can't see any trapdoor here.")
  (IF OBJECT=TRAPDOOR THEN
    TELL "It is a sturdy timber trapdoor, with a large recessed hoop to lift so it can be swung open. There is a small keyhole just beneath the hoop.")

  (IF OBJECT=CLOCK AND ROOM.CLOCK=CARRIED THEN
    TELL "It is a fine carriage clock, with two little pointy hands that point at roman numerals. It has a key on the back to wind it up.")
  (IF OBJECT=CLOCK AND ROOM.CLOCK=ROOM.PLAYER THEN
    TELL "It is a fine carriage clock, with two little pointy hands that point at roman numerals. It has a key on the back to wind it up.")

  (IF OBJECT=PERSIAN_RUG AND ROOM.PLAYER<>LIVING_ROOM THEN
    TELL "What rug?")
  (IF OBJECT=PERSIAN_RUG THEN
    TELL "It's a beautifully woven rug, with intricate details in purple and red. It is very thick and heavy, but you could probably lift back a corner if you tried.")

  (IF OBJECT=TABLE AND ROOM.PLAYER<>KITCHEN THEN
    TELL "What table?")
  (IF OBJECT=TABLE THEN
    TELL "It's an old, sturdy table. Given the scratches and dents spread over its surface, it has seen a lot of service.")

  (TELL "I'm sorry, I haven't been given words to describe that. It's probably not important eh?")
>

<ROUTINE READ_ROUTINE
  (IF ROOM.THIS<>CARRIED AND ROOM.THIS<>ROOM.PLAYER THEN
  (TELL "I can't see any % here to read.")

  (TELL "I don't know how to read that.")
>

<ROUTINE LIFT_ROUTINE
  (TELL "I'm sorry, I don't know how to lift that.")
>

<ROUTINE SCORE_ROUTINE
  (SHOWSCORE)
>



EOF!

; -----------END OF SAMPLE CODE--------------

; the EOF! must exist at the end of the file, with a carriage return (enter key)
; for the parser to recognise the end of the file

; flags recognised by the parser:

; special location values:
; if the location of an object is set to CARRIED, this denotes it is being carried
; if the location of an object is set to NONE, this denotes it does not exist in the world


