-------------------------------------------------------------------------
-- notify.ala (version 1.1)
--      by [email protected], February 2001
--
--      example ALAN program showing a way to notify the player of
--      score changes
--
-- 1999 June, version 1.0
-- 2001 Feb,  version 1.1 update for compatibility with alanlib 0.3.x
--      -renamed closable attribute to closeable
--      -removed * from look_under syntax for compatibility with search etc
-------------------------------------------------------------------------



-- Use the 'proposed standard library' (version 0.3x) for standard verbs etc
$INCLUDE 'std.i'



------------------------- Notification Stuff ----------------------------

ACTOR hero
       HAS oldscore 0.     --records previous score so 'checkscore' event
                                               --      can compare with the current score
       IS notify_on.       --set by 'notify' verb, records whether
                                               --      player wants to see score messages or not
       IS NOT seen_notify. --records whether player has seen the notify verb
                                               --      instructions yet
END ACTOR.

----

-- This event is run each turn to check if the game score is greater than
-- the last recorded score (which is stored in the Hero's 'oldscore'
-- attribute). If the score is greater then the 'Score has gone up...'
-- text is displayed (as long as the player hasn't disabled it by using the
-- 'notify' verb - which sets 'notify_on' to off; ie; 'IS NOT notify_on'.)
-- NOTE: The ALAN scoring system records the game score in a thing called
--          score. It isn't called score OF anything; its just 'score'.
-- NOTE: This event assumes score can only increase, if score can go
--           down then would need to modify this code a bit.
EVENT checkscore
       IF oldscore OF hero < score THEN
               IF hero IS notify_on THEN  -- ie: the player wants to see
                                                                  -- score msgs

                       "$i(Your score has gone up by"
                       SAY (score - oldscore OF hero).
                       "points."

                       -- this msg only displayed first time score changes
                       -- (unless player has already used 'notify' to disable
                       -- notification - in which case it isn't displayed at all.)
                       IF hero IS NOT seen_notify THEN
                               MAKE hero seen_notify.
                               "You can use the NOTIFY command
                               to disable score change
                               messages like this one."
                       END IF.

                       "$$)"

               END IF.
                       SET oldscore OF hero TO score.
       END IF.
       -- run the 'checkscore' event again next turn
       SCHEDULE checkscore AT hero AFTER 1.
END EVENT.

----

-- 'notify' verb allows the players to disable the score change
-- messages. (Some players find such messages annoying.)
-- the verb toggles the hero's 'notify_on' attribute on and off. That
-- attribute is checked by the 'checkscore' event to determine whether
-- to display the score msg or not.

SYNTAX
       notify = notify.

VERB notify
       DOES
               IF hero IS notify_on THEN
                       MAKE hero NOT notify_on.
                       "Score notification is now disabled. (You can turn it back
                       on using the NOTIFY command again.)"
               ELSE
                       MAKE hero notify_on.
                       "Score notification is now enabled. (You can turn it off
                       using the NOTIFY command again.)"
               END IF.
END VERB.



---------------------------The "Game" Stuff ----------------------------

LOCATION threshold NAME 'On' the threshold

       EXIT north TO winmessage
               CHECK door IS NOT closed
                       ELSE "The door isn't open."
       END EXIT.

END LOCATION.



LOCATION winmessage NAME 'Congratulations ...'
DESCRIPTION
       "$i .... you've won the game!$p"
       SCORE.
       QUIT.
END LOCATION.

----

-- a new verb so the player can 'look under mat'

SYNTAX look_under = 'look' under (obj)
       WHERE obj ISA OBJECT OR ACTOR
               ELSE "You can't look under that."

VERB look_under
       DOES
               "You can't look under that."
END VERB.

-- so the player can 'lift mat'
SYNONYMS lift = search.

----

OBJECT door AT threshold
IS NOT takeable.
IS closeable.
IS closed.
IS lockable.
IS locked.

DESCRIPTION
       "There is a"

       IF door IS closed THEN
               "closed"
       ELSE
               "open"
       END IF.

       "door to the north."



       -- most of the code for these verbs is in the standard library
       -- there's just a few extra bits needed here for this particular
       -- game. eg: checking if door is locked in the open verb and the
       -- awarding of points for some actions

       VERB Open
               CHECK door IS NOT locked
                       ELSE "The door seems to be locked."
               DOES
                       SCORE 3.
       END VERB.

       VERB unlock
               CHECK doorkey IN Inventory
                       ELSE "You'll need a key to unlock it."
               DOES
                       -- this event also run if player uses the unlock_with verb
                       -- I can't combine the two verbs ('VERB unlock, unlock_with')
                       -- because the two verbs have incompatible SYNTAX's (see
                       -- lock.i in the standard library files for their syntaxes.)
                       -- see the comments with the events later in this source code
                       -- for reasons why I used an event rather than just repeated
                       -- the required text in each verb.
                       SCHEDULE door_unlocked AT hero AFTER 0.
       END VERB.

       VERB unlock_with
               CHECK door IS closed
                       ELSE "The door is open!"
               AND key = doorkey
                       ELSE "The $2 doesn't seem to be the right
                                       thing to unlock this door."
               DOES
                       -- (also scheduled by unlock verb, see comments there)
                       SCHEDULE door_unlocked AT hero AFTER 0.
       END VERB.

END OBJECT.



OBJECT mat AT threshold

       VERB take, pick_up1, pick_up2
               DOES
                       IF doorkey IS NOT found THEN
                               -- (event also used in 'search' verb below, see
                               -- comments in 'unlock' verb above about this technique.)
                               SCHEDULE find_key AT hero AFTER 0.
                       END IF.
       END VERB.

       VERB search, look_under
               DOES ONLY
                       IF doorkey IS NOT found THEN
                               -- (event also used in 'take' verb above, see comments
                               -- in 'unlock' verb further above about this technique.)
                               SCHEDULE find_key AT hero AFTER 0.
                       ELSE
                               "You find nothing unusual."
                       END IF.
       END VERB.

       VERB examine, look_at
               DOES ONLY
                       "Its a pretty ordinary mat"
                       IF doorkey IS NOT found THEN
                               "with a slight lump where something seems to
                               be lying beneath it"
                       END IF.
                       "$$."
       END VERB.

END OBJECT.



OBJECT doorkey NAME key
IS NOT found.

       VERB take, pick_up1, pick_up2
               DOES
                       SCORE 2.
       END VERB.

END OBJECT.

----

-- These two events are scheduled by verbs in the door object. These events
-- are run in the same turn as the player uses the verbs (ie: 'AFTER 0')
-- There are three reasons for using these events rather than just having the
-- code in the verbs:
--      - The code would need to be repeated in two or more verbs so using
--          events saves the programmer a little repetitive typing
--      - If the 'SCORE' statements in these verbs were repeated in two
--          or more verbs then ALAN would add the total value of those
--          repeated 'SCORE's to the game's maximum points which would
--          then make the game's maximum points figure unattainable by
--          the player
--      - It gives me a chance to demonstrate that the checkscore event
--          must be SCHEDULE'd to run again (AFTER 0 turns) by any events
--          that change the score and weren't SCHEDULE'd in the START
--          section. This is because the checkscore event that
--          is run every turn (by the checkscore event SCHEDULE'ing itself
--          each turn to run AFTER 1) will be executed before these extra
--          events are (because ALAN executes events in the order in which
--          they were scheduled.) So these events SCHEDULE an extra execution
--          of checkevent which will be run on the current turn ('AFTER 0')
--          in order to catch the score changes and notify the player about
--          them on the current turn.

-- A little further explanation of that third point ....

-- The ALAN order of execution on each player turn is:
--        - execute the player command
--        - check any defined 'RULES'
--        - execute each actor's current script
--        -    (checking the RULES again after each script)
--        - execute each event scheduled for this turn (in the
--                                    order they were scheduled)
--        - end of turn (wait for next player input)

-- So in this example where executing the  player's command
-- schedules an event to executed on the current turn the order is:
--        - execute player command - eg 'unlock door'-
--                    (which schedules event 'door_unlocked' to happen
--                    'after 0' turns, ie: this turn.)
--        - check the rules (aren't any)
--        - execute scripts (aren't any)
--        - check rules again (no scripts so no need)
--        - execute events
--                - 'checkscore' (scheduled to run 'after 1' by the
--                   previous turn)
--                         - "nope, score not changed"
--                         - schedules 'checkscore' to run *next* turn
--
--                - 'door_unlocked' (scheduled on this turn by 'unlock'
--                   verb)
--                         - increases the score
--                         - schedules 'checkscore' to run again on
--                           *this* turn
--
--                - 'checkscore' (just scheduled by 'door_unlocked)
--                         - "hmmm score's gone up! display msg!"
--                         - schedule 'checkscore' to run *next* turn
--                           (already scheduled by previous score but
--                           no problem - Alan doesn't run it twice
--                           next turn or anything.)
--        - end of turn


EVENT find_key
       "Lifting the mat reveals a key."
       MAKE doorkey found.
       LOCATE doorkey HERE.
       SCORE 2.
       SCHEDULE checkscore AT hero AFTER 0.
END EVENT.


EVENT door_unlocked
       SCORE 3.
       SCHEDULE checkscore AT hero AFTER 0.
END EVENT.


--------------------------- Start Section ----------------------------
START AT threshold.

"'Notify' - ALAN game showing how to program score change messages
$iby [email protected]"

"$pBrief summary
$i- use an attribute to record the current score.
$i- run an event each turn to check if player's score now changed from
the recorded score. (And display a message if its changed.)
$i- note need to ensure the 'check score' event is run after any other
events that might affect the score. (An event changing player score is
probably a rare occurence but there's examples in this demo game.)
$i- provide a way for the player to turn off the score messages if they
want (eg: a 'notify' verb like in this demo.)
$i- Look at the source code for more details."

"$p---------------------------------------------------------------
$nNow let's play the game ..... You need to get through this door."

SCHEDULE checkscore AT hero AFTER 0.