;------------------------------------------------------------------------------------------
; 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 beneath the living room.")
  (DESC "Basement")
  (FLAGS )
  (UP PER TRAPDOOR)
  (ACTION BASEMENT_ROUTINE)
>


; 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 "This is a demo text adventure created using the ZILish adventure description language. Explore, investigate and find your way to the secret room. Use simple instructions to tell me what to do, eg, get axe, go west etc.")
  (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 under the debris 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 TABLE
  (SYNONYM TABLE)
  (DESC "table")
  (FDESC "A large kitchen table sits centrally in the room.")
  (LOC KITCHEN)
  (FLAGS )
  (SIZE 100)>

<OBJECT CLOCK
  (SYNONYM CLOCK)
  (DESC "carriage clock")
  (FDESC "A fine looking carriage clock sits on the table.")
  (LDESC "A carriage clock is here.")
  (LOC KITCHEN)
  (ACTION CLOCK_ROUTINE)
  (FLAGS )
  (SIZE 5)>

<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 OPEN
  (SYNONYM OPEN)
  (ACTION OPEN_ROUTINE)>

<VERB EAT
  (SYNONYM EAT MUNCH CONSUME)
  (ACTION EAT_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)>

<VERB WIND
  (SYNONYM WIND)
  (ACTION WIND_ROUTINE)>

<VERB PUT
  (SYNONYM PUT INSERT)
  (ACTION PUT_ROUTINE)>

<VERB THROW
  (SYNONYM THROW LAUNCH LOB HURL)
  (ACTION THROW_ROUTINE)>

<VERB FIGHT
  (SYNONYM FIGHT ATTACK HIT)
  (ACTION FIGHT_ROUTINE)>

<VERB SCORE
  (SYNONYM SCORE)
  (ACTION SCORE_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.
