#### Cloak of Darkness #############################################
#
# The '#' sign denotes comments. The comment separator lines
# are arbitrary and used merely as a visual aid.
#
Name    Cloak of Darkness
Version 1.3
Style   A-code 12
Author  Mike Arnautov
Date    20 Nov 2009
#
# Let's have some verbs.
#
verb go, walk, proceed           # These are all synonymous
verb north, =n                   # Echo "north" if player says "n"
verb northeast, =ne
verb east, =e
verb southeast, =se
verb south, =s
verb southwest, =sw
verb west, =w
verb northwest, =nw
verb out, =exit
verb look, =l, examine
verb read
verb inventory, =i
verb drop, =dr
verb hang
verb quit
#
noun wall, wallpaper
#
#-------------------------------------------------------------------
#
# We only need one variable. The "status" variable is mandatory, so it
# would have been declared for us automatically anyway, but let's be
# proper.
#
variable status
variable context  # Dummy -- only here to force CGI mode's availability
#
#-------------------------------------------------------------------
#
# Declare words to ignore.
#
noise    and,the,a,it,an,that,this,to,at,with,room
#
#-------------------------------------------------------------------
#
# Declare "random" texts. (NB, A-code is case insensitive; upper case
# is used in text, place and object declarations for ease "grepping"
# through A-code source files.)
#
# A-code engine does its own text formatting, so line splits and are
# largely irrelevant and leading spaces are ignored.
#
text HERE.WE.ARE        # The '+' prefix centres the line

  +             The Cloak of Darkness (version 1.3)

   Hurrying through the rainswept November night, you're glad 
   to see the bright lights of the Opera House. It's surprising 
   that there aren't more people about but, hey, what do you
   expect in a cheap demo game...?

#
text NO.GO.OUT
   You've only just arrived, and besides, the weather outside
   seems to be getting worse.
#
text CLOAK.HUNG
   You hang the cloak on the hook.
#
# Text in square brackets is a "text switch", consisting of '/'
# delimited components. The '/' outside a switch and at the beginning of
# a line, is skipped, but causes subsequent blanks to be honoured.
# This text will be printed using the state of the object MESSAGE as the
# qualifier. If the message is still readable, the outcome will be WON.
# If the state of message is zero (it is no longer readable) the
# outcome will be displayed as LOST. Note that we could have tied
# the state of this text to the state of the MESSAGE in the bar, but
# instead, we'll just use MESSAGE as an explicit qualifier.
#
text THE.OUTCOME
   The message[ has been carelessly trampled, making it difficult
   to read. You can just distinguish the words.../, neatly marked
   in the sawdust, reads...]

   /                          YOU HAVE [LOST/WON] !!!

#
text NO.HANG.CLOAK
   There is nowhere to hang the cloak around here!
#
text ITS.ALREADY.HANGING
   The cloak is already hung up!
#
text MIGHT.DISTURB.THINGS
   I have a better idea: let's get out of here before you 
   disturb anything.
#
text IT.IS.DARK
   It is dark in here!
#
text NOTHING.TO.READ
   There's nothing here one could read!
#
text NO.DROP.CLOAK
   This isn't the best place to leave a smart cloak lying around.
#
text EMPTY.HANDS
   You are empty-handed.
#
text TOTING
   You are carrying:
#
text NO.COMPRENDE          # The '#' will be replaced by a word.
   Sorry, I don't understand "#".
#
text DUNNO.HOW
   Sorry, I have no idea how to do that.
#
text I.DONT.SEE
   I see no # here!
#
text OK.LETS.QUIT
   As you wish!...

#
text WHICH.WAY?
   Which way do you want to #?
#
text cycle NO.WAY
   [Ahem... //]There [is no way to go # from here/are no # exits
   here/is no way # from here/is no exit leading # from here].
#
text its.a.wall
   The wallpaper [is faded a bit, but still manages to look opulent/has
   seen better days].
#
#-------------------------------------------------------------------
#
# Now the locations... For simplicity we only have a single description
# per location, not differentiating between short and long descriptions.
#
place +HALL          # The '+' prefix adds location name to vocabulary
   You are standing in a spacious hall, splendidly decorated in red
   and gold, with glittering chandeliers overhead. The entrance from
   the street is to the north, and there are doorways south and west.
#
#...................................................................
#
place CLOAKROOM
   The walls of this small room were clearly once lined with hooks,
   though now only one remains. The exit is a door to the east.
#
#...................................................................
#
place +BAR
   The bar, much roughers than you'd have 
   guessed after the opulence of the foyer to the north, is 
   completely empty.
#
#-------------------------------------------------------------------
#
# And objects... These have up to three descriptions each. The first
# is the inventory description, the second (delimited by '%')
# is a "here is" one and the third (delimited by '&') is the "examine"
# description. Any or all of these may be absent.
#
object HOOK, =BRASS, PEG
  %
   There is a brass hook here.
  &It's just a small brass hook, screwed into the wall.[/ Your
   velvet cloak is now hung upon it.]
#
#...................................................................
#
# The cloak only has two states: worn or hanging. When worn, only
# the "in hand" description can be produced, so the "here is" description
# does not need to describe anything other than the hanging cloak.
# There *could* have been 3 or even 4 different states (worn, carried,
# on the floor, and hanging on the peg) in which case the "here is"
# description would also have to contain a text switch to allow for
# the last two states. And the detailed description may (but need not)
# profitably be modified by the cloak state as well.
#
object CLOAK, =VELVET, =HANDSOME
   A velvet cloak[ (worn)/]
  %A black velvet cloak hangs on the hook.
  &It is a handsome cloak, of velvet trimmed with satin, and slightly
   spattered with raindrops. Its blackness is so deep that it
   almost seems to suck light from the room.
#
#...................................................................
#
# Can't carry it, and we don't bother with the detailed description,
# because examining the message is handled quite separately and ends the
# 
object MESSAGE, SAWDUST, FLOOR
  %
   There seems to be some sort of message [scrawled/neatly written]
   in the sawdust on the floor.         
#
#-------------------------------------------------------------------
#
# For source readability, let's also declare some symbolic names
# for states and flags.
#
state 1, hung        # We don't want zero default, so specify a value
#
flags variable       # The below flags are associatedwith variables.
      moved          # So this is 1
#
flags place          # Places may be dark or lit
      lit
#
#-------------------------------------------------------------------
#
# We only need one procedure for this demo.
#
proc describe.here
   local obj.ptr                    # This is a variable local to this routine
#
   ifflag here, lit
      say here                      # Give location description
      itobj obj.ptr                 # Loop through all objects
         ifhere obj.ptr             # If object is here...
            say obj.ptr             # ...describe it
         fin
      fin
   else
      say it.is.dark
   fin
#
#-------------------------------------------------------------------
#
# Let's define code associated with individual locations.
#
at bar
   move n, out, hall, hall          # Move to hall, if so commanded, then "quit"
   ifgt message, 0                  # If message readable,
      sub message, 1                # ...disturb it.
   fin
   ifflag here, lit
      ifkey look
         respond wall, its.a.wall, 1
         ifkey message
            call read
         fin
      fin
      proceed
   fin
#
   ifkey quit                       # He may wish to quit in the dark
      call quit
   fin
   ifgt message, 0               # Message still readable?
      sub message, 1             # He trod on it in the dark!
   fin 
   quip might.disturb.things     # Warn him!
#
#...................................................................
#
at cloakroom
   move e, out, hall, hall
   ifkey hang, cloak                # He wants to hang up the cloak
      ifeq cloak, hung              # But perhaps it is hanging already?
         quip its.already.hanging
      fin
      set cloak, hung               # Mark the cloak as hung
      set hook, hung                # Mark the peg as having the cloak on it
      drop cloak
      flag bar, lit                 # Light up the bar
      quip cloak.hung
   fin
#
#...................................................................
#  
at hall
   move w, cloakroom
   move s, bar
   respond n, out, no.go.out
#
#-------------------------------------------------------------------
#
# Now code associated with individual verbs.
#
# Generalised action HANG simply fails. The code specific to the
# cloakroom is handled by the AT CLOAKROOM directive. This is merely a
# question of style -- it could be just as well handled here, by using
# the IFAT CLOAKROOM test.
#
action hang cloak     
   ifnear cloak           # The cloak is here, butu not being held
      quip no.hang.cloak
   fin
#
#...................................................................
#
action drop               # Dropping not allowed!
   quip no.drop.cloak
#
#
#...................................................................
#
# List inventory
#
action inventory
   local tmp.val
   local obj.ptr
#
   set tmp.val, 0          # Nothing listed so far
   itobj obj.ptr           # Loop through all objects
      ifhave obj.ptr       # Is the player carrying this one?
         ifeq tmp.val, 0   # Have we listed anything so far?
            say toting     # Give the "you are carrying" header
         fin
         say obj.ptr       # List object
         add tmp.val, 1    # Note we listed one
      fin
   fin
   ifeq tmp.val, 0         # Did we find anything?
      say empty.hands      # If not, report the fact
   fin
   quit                    # In either case, we are done with this command
#
#...................................................................
#
# Look on its own is a request for the long description os the current
# location. When coupled with an object, it is a request to examine 
# the object. (We've declared look and examine to be synonyms!)
#
action look
   ifflag here, lit
   else
      quip it.is.dark
   fin
   ifeq status, 1          # No object specified
      call describe.here   # Call our location decsribing routine
      quit
   fin
   respond wall, its.a.wall, 0
   ifnear arg2          # Is the whatever nearby?
      describe arg2     # Use the built-in command
   else
      say i.dont.see, arg2
   fin
   quit                    # Abort further command processing
#
#...................................................................
#
action read
   ifflag here, lit
   else
      quip it.is.dark
   fin
   ifkey message
      or
   ifeq status, 1
      and
   ifnear message
      say the.outcome, message
      stop
   fin
   ifeq status, 1
      quip nothing.to.read
   fin
#
#...................................................................
#
# Generally speaking, movements are specific to locations, hence
# they are handle in location specific "at" sections, which get
# processed before "action" sections. Hence we only get here if
# the move didn't work for some reason.
#
action walk
   ifeq status, 1             # No direction supplied
      quip which.way?, arg1   # Query for it
   fin
#
#...................................................................
#
# Quit the game.
#
action quit
   say ok.lets.quit
   stop                       # Terminate the program.
#
#-------------------------------------------------------------------
#
# Some debugging commands and all associated entities live in a
# sperate module which is included if present and quietly ignored
# otherwise.
#
include? debug.acd          # Optional standalone debugging module
#
#-------------------------------------------------------------------
#
# Initialisation section is executed once only on game start.
#
init     
   flag hall, lit           # Note which locations are lit
   flag cloakroom, lit
   apport message, bar      # Move things where they belong
   apport hook, cloakroom
   get cloak                # The player is holding the cloak
   set message, 4        
   set context, 0           # Keep the translator happy
#
   goto hall                # Go to the start location
   say here.we.are
#
#-------------------------------------------------------------------
#
# Main loop.
#
repeat
#
# Let's see whether we need to dscribe the location.
#
   ifflag status, moved          # If player moved, describe new location
      unflag status, moved
      call describe.here
   fin
#
# Get player input, and make sure we understood the words.
#
   input                         # Get player input
   ifeq arg1, badword            # If verb unknown...
      or
   ifeq arg1, ambigword          # ...or ambiguous...
      quip no.comprende, arg1    # ...complain and "quit".
   fin
   ifeq arg2, badword            # Ditto for the object.
      or
   ifeq arg2, ambigword
      quip no.comprende, arg2
   fin
#
# There are no split directions in this game.
#
   ifany ne, se, sw, nw
      ifeq status, 1
         quip no.way, arg1
      else
         quip no.way, arg2
      fin
   fin
# 
# Time to process the command. Remember that a called routine may
# decide to abort further processing, so that execution jumps to the
# top of the (first) repeat section.
#
   call here                     # Do any processing specific to this location
   call arg1                     # If still here, do verb processing
#
   ifgt status, 1                # Still here -- command not understood.
#      and
#   ifflag arg2, object
      and
      not
   ifnear arg2                   # Maybe because the object isn't here?
      quip i.dont.see, arg2
   fin
   ifeq status, 1
      and
   ifinrange arg1, north, nw
#   ifany north, east, west, south
      quip no.way, arg1
   fin   
   quip dunno.how                # Sorry -- don't understand!
#
# After this we loop back to the top of repeat sections.
#
############################################################################
