;------------------------------------------------------------------------------------------
; ZILish adventure description language (ADL) for the colour maximite 2. By John Gill 2024.
;------------------------------------------------------------------------------------------

; based on the infocom ZIL from the classic lat 1970's early 80s text adventure games.
; Watch out for the grues.

; there are four types of entry in the ZILish ADL. they are:

; ROOM
; OBJECT
; VERB
; ROUTINE

; the ROOM, OBJECT and VERB entries are all stored in one .txt file 
; this file must be called adventure.txt and it must exist in the same folder as the parser.

; the ROUTINE entries are all stored in a separate .txt file called actions.txt
; see comments in actions.txt for details on creating ROUTINEs
; ROUTINEs can be referenced by ROOMs, OBJECTs, and VERBs in the adventure.txt file.

; unlike the original infocom ZIL, these two files are all you need to make a complete adventure
; they are directly parsed by the ZILish interpreter on the CMM2

;-------------------------------------------------------
; SYNTAX FOR CREATING AN ENTRY IN THE adventure.txt FILE
;-------------------------------------------------------

; every entry begins with a < and is immediately followed by the entry type, 
; <ROOM or <OBJECT or <VERB
; any other declaration will result in a parse error.

; then there is a single space followed by the internal reference name for this entry
; this reference name is never written on screen, it is only used by the programmer to uniquely
; identify that particular room/object/verb to the ZILish interpreter.
; This reference name must be a single word and must not have any spaces in it or it'll
; confuse the parser - underscores are OK.

; Each reference name must be unique - for example you cannot have two OBJECTs both given 
; the internal reference name "KEY", you have to distinguish between them
; for example "TRAPDOOR_KEY" and "FRONT_DOOR_KEY"

; likewise, you cannot have two ROOMs given the same internal reference name.
; if you have maze ROOMs, each ROOM must have a unique internal reference name
; (eg, MAZE_1, MAZE_2, MAZE_3 etc)
; note of course that if you wish, the different maze room descriptions can all be alike!
; (a twisty little maze of passages...)

; each entry is then followed by a number of sub-items, each one contained within
; normal brackets (.....)

; note each sub-item line is limited by the CMM2 string limit of 256 characters per line
; at the end of all the sub-items, the entry is closed with a >

; then the next entry can begin < etc...

; the entries can appear in any order, you can mix up <ROOM, <OBJECT and <VERB types 
; to aid debugging/readability of the adventure, the parser doesn't care what order they are in



; ------------
; ROOM entries
; ------------

; a room is a single location within the game. It doesn't have to be an actual room.
; it could be an outside space, a corridor, or even just part of a room.
; each ROOM is connected to other ROOMs in the ZILish file using the "TO" and "PER" sub-items
; (see below for full description of room sub-items)

; here is a "normal" game ROOM:

<ROOM LIVING_ROOM
  (FDESC "You are in a pleasant living room. The walls are painted custard yellow.")
  (DESC "Living Room")
  (EAST TO KITCHEN)
  (WEST TO STRANGE_PASSAGE IF CYCLOPS_GONE ELSE 'The cyclops won't let you pass. It glares at you menacingly.')
  (DOWN PER TRAPDOOR)
  (ACTION LIVING_ROOM_ROUTINE)
  (FLAGS LIGHTSON)>

; the indent spaces before the sub-items are ignored by the parser,
; they're just there to make reading the ZILish text file easier.

; SUB-ITEMS for a ROOM
; --------------------
; the order of the sub-items doesn't matter, as long as they're each contained within
; brackets (...) and the final one terminates the whole room entry with a >

; each ROOM must have an FDESC (full description) -
; this is what is written on the screen the first time the player enters that location.
; each ROOM must also have a DESC (short description) -
; this is what is written on the screen when the player returns to a location he/she has
; already visited.

; the connections to other ROOMS (if any) need to be added as shown above, one sub-item per exit.
; Note there could be *no* exits - there could be a room that you cannot get into or out of
; by simply walking! ; note that each exit (east, west etc) can be either TO or PER.

; TO means you can go there just by going north, east, west etc (the cardinal directions)
; Note that exiting TO another ROOM can be conditional using IF ... ELSE and then referring to 
; one of the FLAGs for this ROOM (see FLAGs below). In the LIVING_ROOM example above, if the
; player tried to go west to the strange passage, and the CYCLOPS_GONE flag is UNSET (not present)
; then this would not happen, they'd just get the message "The cyclops won't let you pass... etc"

; PER exits mean there is a door type object that needs to be negotiated to move between the 
; two locations it joins. See under OBJECTs below for details on managing door type objects.
; Note that a door type object doesn't necessary need to be a door - it could be a portal, 
; a trapdoor, or any other thing that can be locked, unlocked, opened and closed between locations.

; the (ACTION ...) sub-item refers to this ROOM's ROUTINE entry in the actions.txt file 
; this ROUTINE is executed every time the player enters the room, after the room description
; has appeared on screen. 
; This is used to display conditional descriptions like, "The gear is rotating clockwise" etc

; FLAGS are conditions specific to this room only, for example if the light is on 
; or if a tap is running etc. 
; Note flags are not variables - they are yes/no, on/off
; If the FLAG word is present, it means it is SET.
; If the FLAG is not present, it means it is UNSET. These are the terms used in ROUTINEs.

; ---- more sample room code --------

<ROOM KITCHEN
  (FDESC "You are in the kitchen. It is beautifully decorated in 1970s brown and tan squares.")
  (DESC "Kitchen")
  (WEST TO LIVING_ROOM)
  (FLAGS LIGHTSON NOTHIEF)
  (ACTION KITCHEN_ROUTINE)>

<ROOM STRANGE_PASSAGE
  (FDESC "You are in a strange, stone passage. Green slime is smeared down the walls. There is a thick layer of dust and debris covering the floor.")
  (DESC "Strange passage")
  (EAST TO LIVING_ROOM)>

<ROOM BASEMENT
  (FDESC "You are in a dimly lit basement. Congratulations, you have found the secret room at the end of this demo adventure! Now go and make your own!")
  (DESC "Basement")
  (FLAGS )
  (UP PER TRAPDOOR)>

; note that you can create ROOM links such that going west from one ROOM doesn't necessarily mean
; that going east again will take you back to the ROOM you just came from - great for mazes!

; --------------
; OBJECT entries
; --------------

; here is a "normal" game object:

<OBJECT LANTERN
  (SYNONYM LAMP LANTERN)
  (FDESC "A battery-powered brass lantern is on the trophy case.")
  (LDESC "There is a brass lantern here.")
  (DESC "brass lantern")
  (LOC LIVING_ROOM)
  (ACTION LANTERN_ROUTINE)
  (ADJECTIVE BRASS)
  (FLAGS )
  (SIZE 15)>

; (SYNONYM) is a compulsory entry. It is a list of words separated by spaces that the user 
; can type in that will refer to this object. Note that there *must* be at least one synonym
; for each object, otherwise the player will not be able to interact with it. 
; In the above example, the player could type in lamp or lantern, and the interpreter will
; recognise it as the object with internal name LANTERN

; note that there could be two objects that both share a common synonym. 
; eg., small key and brass key could both have the synonym key. If both keys are present,
; the parser will query the player which one they mean by use of ADJECTIVEs (see below)

; (FDESC) for OBJECTS is similar to the ROOM entry - it is the full description of the object 
; as it first appears in the game before the player has picked it up (eg, on a shelf etc)

; (LDESC) is a shorter description of the object which is used when the player has just put the
; object down on the floor. (Internally, ZILish adds the flag REMOVED to an object once it has
; been picked up so it knows to use the LDESC from then on if the object is put down anywhere.)

; (LOC) is the ROOM name where the object is first located. LOC can also be assigned the value NONE
; which means it doesn't physically exist in the game, and doesn't appear anywhere.
; Useful for making objects disappear (eg, food after it's been eaten). 
; LOC can also be given the value CARRIED, which means it is in the player's inventory.

; (DESC) is the brief description of the object as it shows in the player's inventory.

; (ADJECTIVE) are additional words that the player can optionally enter which will distinguish two
; similar objects that could both be in the same location.

; For example, the player could be carrying a small rusty key, and a large iron key. 
; if the player enters "drop key", the parser will ask the player for an adjective so it knows
; which one to drop.

; Note that an object that is being carried by the player is considered to be "in the same location"
; as the room the player is currently in, as far as the parser is concerned.

; (ACTION) is just like in ROOMs, it has a single word following it that references a specific 
; ROUTINE in actions.txt to describe how that object behaves when it is referred to by the player

; (FLAGS) is just like in ROOMs, it is a list of single words that indicate the status of
; that object - for example, if a lamp is on or off. Like ROOM FLAGs, OBJECT FLAGS are not
; variables - they are either present (SET) or not present (UNSET). Note, in the lantern example
; above, there is an UNLIT FLAG set. So to turn the lamp on, you would UNSET the UNLIT flag.
; Alternatively, you could decide to have a LIT FLAG that is UNSET when the lamp is off, and then 
; SET it when the lamp is turned on. Either of these solutions are handled fine by the parser,
; it's up to you how you want to code the flags, whichever makes coding your adventure easier.

; One exception is door type objects. There are some FLAGS hard coded into ZILish to deal with
; door behaviour. All doors have a LOCKED and OPEN flag. If the LOCKED flag is SET, the door is
; locked. When the door is unlocked, the LOCKED flag is UNSET. A closed door has the OPEN flag
; UNSET. Once opened, the OPEN flag is SET. Note that it is a nonsense for a door type object to
; have both the LOCKED and OPEN flags SET, if you do this it will cause unexpected behaviour in
; door type objects.

; (SIZE) is a measure of how large or heavy something is
; I've set the player's initial max carry at 60, anything over that is too large/heavy to carry
; ZIL has a hard-coded size value of 100 to signify something that is fixed in place or impossible
; to take - for example, a cupboard attached to a wall.

-------------
PLAYER object
-------------

; there has to be one and only one special kind of object in the game, called PLAYER. 
; this holds the player's start location in the game, and the maximum they can carry (encumberance)
; and their initial encumberance (usually 0, but doesn't have to be)
; the internal reference name in the <OBJECT ... declaration line must be PLAYER 
; for the ZILish interpreter to recognise it as the player.

<OBJECT PLAYER
  (LOC LIVING_ROOM)
  (FDESC "Welcome to this adventure game. This is the intro spiel. Yada yada yada. "Go north", "get axe" you know the kind of thing. Good luck!")
  (SIZE 60 0)>

; the player object must have a starting location (LOC) sub-item. This must be a valid
; internal room reference name. 
; The FDESC holds the introductory waffle to the game. One limitation is that this can only be 
; a maximum 247 characters long (256 - (FDESC ) due to the string length limitation of CMM2 BASIC. 
; This is something I'd like to fix in future to allow longer intro spiel.

; in the player object, (SIZE) gives two numbers separated by one space - the first is the total 
; amount of stuff they can carry, followed by how much they're actually carrying, which starts at 0
; but could start at more if you want the player to be encumbered when the game begins.

; here's some more sample objects:

<OBJECT PERSIAN_RUG
  (DESC "Persian rug")
  (FDESC "A rather ornate Persian rug covers most of the middle of the room.")
  (LOC LIVING_ROOM)
  (ACTION PERSIAN_RUG_ROUTINE)
  (SYNONYM RUG CARPET)
  (ADJECTIVE PERSIAN)
  (FLAGS )
  (SIZE 100)>

<OBJECT CYCLOPS
  (DESC "Cyclops")
  (FDESC "A menacing looking cyclops is guarding the door to the west.")
  (LOC NONE)
  (ACTION CYCLOPS_ROUTINE)
  (SYNONYM CYCLOPS CREATURE MONSTER)
  (ADJECTIVE MENACING)
  (FLAGS )
  (SIZE 100)>

<OBJECT TRAPDOOR_KEY
  (SYNONYM KEY)
  (DESC "small rusty key")
  (FDESC "A small rusty key is lying half hidden in the dust on the floor.")
  (LDESC "There's a small rusty key here.")
  (LOC NONE)
  (ACTION TRAPDOOR_KEY_ROUTINE)
  (ADJECTIVE SMALL RUSTY)
  (FLAGS )
  (SIZE 1)>

<OBJECT DEBRIS
  (SYNONYM DUST DEBRIS)
  (LOC NONE)
  (FLAGS )
  (SIZE 100)>

<OBJECT IRON_KEY
  (SYNONYM KEY)
  (DESC "large decorative iron key")
  (FDESC "A large, decorative iron key is hanging from the wall.")
  (LDESC "There's a large, decorative iron key on the floor here.")
  (ADJECTIVE LARGE IRON DECORATIVE)
  (LOC LIVING_ROOM)
  (ACTION IRON_KEY_ROUTINE)
  (FLAGS )
  (SIZE 1)>

<OBJECT CUPBOARD
  (SYNONYM CUPBOARD CABINET)
  (DESC "cupboard")
  (FDESC "An old wooden cupboard perches precariously on the wall.")
  (LOC KITCHEN)
  (ACTION CUPBOARD_ROUTINE)
  (ADJECTIVE WOODEN)
  (FLAGS LOCKED)
  (SIZE 100)>

<OBJECT NOTE
  (SYNONYM NOTE SCRAP)
  (DESC "note")
  (FDESC "A little scrap of paper sits on the otherwise empty shelves of the cupboard. It has some writing on it.")
  (LDESC "There's a little note on the floor here.")
  (LOC NONE)
  (ACTION NOTE_ROUTINE)
  (FLAGS )
  (SIZE 1)>

<OBJECT TRAPDOOR
  (SYNONYM TRAP-DOOR TRAPDOOR)
  (DESC "trapdoor")
  (ACTION TRAPDOOR_ROUTINE)
  (SIZE 100)
  (FLAGS LIVING_ROOM BASEMENT LOCKED)>

; -----------------
; door-type objects
; -----------------
; the trapdoor above is a door type object - it connects two locations together.
; there is nothing that specifically identifies it as a door type object, other than the fact
; that it is referenced by at least one ROOM as a PER exit.

; note that it doesn't have a (LOC) entry and so does not exist in either of the locations it joins.
; this means that a door object is not described automatically in either location description
; it is simply listed as an exit (north, east etc)

; a door type object connects two locations together, and it can be accessed from both of those
; locations. the two locations connected by the door are given by the first and second items in 
; the FLAGS list of the door-type object. Note this is the *only* time where ROOM objects 
; can appear in a FLAGS list. The two location *must* appear as the first and second flags.
; Additionally, there are two special flags that the parser looks for on a door-type object:
; LOCKED and OPEN. If a door-type object has the flag LOCKED set, then the parser will not allow
; travel in the direction of that exit. If the door-type object has the OPEN flag unset, the
; parser will not allow travel in the direction of that exit. You can only travel PER a door-type
; exit if its LOCKED flag is UNSET and its OPEN flag is SET.


; -----------------
; EXIT type objects
; -----------------


<OBJECT NORTH
  (SYNONYM NORTH N)
  (DESC "to the north")
  (ACTION EXIT)>

; NORTH is given the ACTION type EXIT, defining it as an exit direction type,
; and it can then be used as a direction of travel for moving between ROOMs with " TO " or " PER " 
; (see ROOM description previously). Note EXIT direction objects don't need a LOC or FDESC
; the DESC simply shows what the interpreter writes on screen when describing visible exits
; from the current location.

<OBJECT EAST
  (SYNONYM EAST E)
  (DESC "to the east")
  (ACTION EXIT)>

<OBJECT SOUTH
  (SYNONYM SOUTH S)
  (DESC "to the south")
  (ACTION EXIT)>

<OBJECT WEST
  (SYNONYM WEST W)
  (DESC "to the west")
  (ACTION EXIT)>

<OBJECT NORTHWEST
  (SYNONYM NORTHWEST NW N-W)
  (DESC "to the north-west")
  (ACTION EXIT)>

<OBJECT NORTHEAST
  (SYNONYM NORTHEAST NE N-E)
  (DESC "to the north-east")
  (ACTION EXIT)>

<OBJECT SOUTHEAST
  (SYNONYM SOUTHEAST SE S-E)
  (DESC "to the south-east")
  (ACTION EXIT)>

<OBJECT SOUTHWEST
  (SYNONYM SOUTHWEST SW S-W)
  (DESC "to the south-west")
  (ACTION EXIT)>

<OBJECT DOWN
  (SYNONYM DOWN D)
  (DESC "down")
  (ACTION EXIT)>

<OBJECT UP
  (SYNONYM UP U)
  (DESC "up")
  (ACTION EXIT)>

<OBJECT IN
  (SYNONYM IN)
  (DESC "in")
  (ACTION EXIT)>

<OBJECT OUT
  (SYNONYM OUT)
  (DESC "out")
  (ACTION EXIT)>

; the three objects below all have their LOC set to "NONE", which means they doesn't physically
; exist in the world. Handy for magic words.

<OBJECT PLUGH
  (SYNONYM PLUGH)
  (ACTION PLUGH_ROUTINE)
  (LOC NONE)>

<OBJECT ON
  (SYNONYM ON)
  (LOC NONE)>

<OBJECT OFF
  (SYNONYM OFF)
  (LOC NONE)>


<OBJECT CYCLOPS_DOOR
  (SYNONYM DOOR)
  (DESC "door")
  (ACTION CYCLOPS_DOOR_ROUTINE)
  (SIZE 100)
  (LOC NONE)>

; note the door above is *not* a DOOR object, it is another null object (LOC is NONE so it doesn't
; physically exist in the game). It means the parser can do something useful with player inputs 
; containing the word "door"




; ------------
; VERB entries
; ------------

; VERB types are the simplest entries, they need only SYNONYNM and ACTION sub-items
; as with ROOMs and OBJECTs, SYNONYMs are the words the player could type in, and the parser will
; recognise it as this verb.

<VERB EAT
  (SYNONYM EAT MUNCH CONSUME)
  (ACTION EAT_ROUTINE)>

<VERB OPEN
  (SYNONYM OPEN)
  (ACTION OPEN_ROUTINE)>

<VERB CLOSE
  (SYNONYM CLOSE SHUT)
  (ACTION CLOSE_ROUTINE)>

<VERB LOCK
  (SYNONYM LOCK)
  (ACTION LOCK_UNLOCK_ROUTINE)>

<VERB UNLOCK
  (SYNONYM UNLOCK)
  (ACTION LOCK_UNLOCK_ROUTINE)>

<VERB SWITCH
  (SYNONYM TURN SWITCH LIGHT)
  (ACTION SWITCH_ROUTINE)>

<VERB GET
  (SYNONYM GET PICK TAKE)
  (ACTION GET_ROUTINE)>

<VERB DROP
  (SYNONYM DROP)
  (ACTION DROP_ROUTINE)>

<VERB INVENTORY
  (SYNONYM INV INVENTORY CARRYING)
  (ACTION INVENTORY_ROUTINE)>

<VERB LIFT
  (SYNONYM LIFT MOVE SLIDE)
  (ACTION LIFT_ROUTINE)>

<VERB LOOK
  (SYNONYM LOOK REDESCRIBE)
  (ACTION LOOK_ROUTINE)>

<VERB EXAMINE
  (SYNONYM EXAMINE EXAM)
  (ACTION EXAMINE_ROUTINE)>

<VERB READ
  (SYNONYM READ)
  (ACTION READ_ROUTINE)>

<VERB SAY
  (SYNONYM SAY SPEAK)
  (ACTION SAY_ROUTINE)>
 

EOF!

; the file must conclude with EOF! followed by carriage return (enter key)
; the interpreter looks for this character combination to know it has reached
; the end of the file and it needn't read any more.
