Here's a bit of a tutorial on how FLOORS were implemented.

First off, as I said in the readme file in this ARC, "Necessity is the mother
of invention."  We hit the compiler limit of ADVSYS and needed to find a way
to incorporate a lot more rooms and objects in order to complete the adventure.
So....I hit upon the idea of recycling objects.  Take old discarded worn out
adventurer's cast off trinkets and turn them into useful valued parts of the
adventure.  Rehabilitation!   We took one of the ice floes in ELVES and turned
it into Santa's Cottage, another icefloe and turned it into the reindeer barn,
turned Frosty The Snowman into a Penguin, etc, etc....  Depending on where you
are in the adventure, these objects appear to you in different forms.

Now for the nuts and bolts.  The whole system is based around the binary
operators built into ADVSYS.  Open your ADVSYS manuals and find (& exp1 exp2)
and (| exp1 exp2).  OK, now here's what we are going to do.  In the old
runtime package there was a room property called "Visited?".  It was a Boolean
operator.  In other words it was set to 0 if you hadn't been there before and
set to 1 if you had.  So all you had to do was to check to see

                  (if Visited? (print $SDESC)(print $LDESC))

In other words if I've been here before give me the short description otherwise
give me the long description of the room.

     Now we are going to complicate matters.  Let's build a tiny adventure
that's a house that's three floors high with four rooms on each floor.  What
we are going to do is actually just define four rooms and set up another
variable in the adventure to keep track which floor we think we are on.  I'll
call the first floor the basemement.  We'll draw the adventure out on paper
so what we'll end up with are three identical floors: Basement, Main and Attic.

                 -------           -------          -------
                | 1 | 2 |         | 1 | 2 |        | 1 | 2 |
                 -------           -------          -------
                | 3 | 4 |         | 3 | 4 |        | 3 | 4 |
                 -------           -------          -------
                 Basement            Main            Attic
 

Now have a peek at this.  If we say Basement = Floor 1, Main = Floor 2, and
Attic = Floor 4. (Notice we skipped 3) Then we can do a bit of bit twiddling
and know exactly where we are and where we've been before.  To do this we
are going to need one more property that will be shared by actors and objects
alike.  We'll set ONFLOOR? to the integer value of the floor we are currently
on.  OK, here comes the binary part.  

Here's a binary to decimal conversion chart.

                  Decimal        Binary
                    00          00000000
                    01          00000001
                    02          00000010
                    03          00000011
                    04          00000100
                    05          00000101
                    06          00000110
                    07          00000111
                    08          00001000
                    16          00010000
                    32          00100000
                    64          01000000
                   128          10000000

OK, now for a quick lesson in bit twiddling.

Let's take the simple ADVSYS expressions 

                            (& 6 16)                   (| 6 16)

            6 in Binary     00000110                   00000110
           16 in Binary     00010000                   00010000
           BITWISE AND      00000000      BITWISE OR   00010110


                            (& 5 7)                    (| 5 7)

            5 in Binary     00000101                   00000101
            7 in Binary     00000111                   00000111
            BITWISE &       00000101       BITWISE |   00000111

If this doesn't refresh your memory on binary math, don't worry, read on and it
will probably become clear.  (Humble apologies to those who are already
conversant with binary crap)

Now getting back to the game.  We are starting the adventure with our hero in
the basement in room 1.  So we set the property ONFLOOR? for him as the integer
value one or binary 00000001.  Also we are going to BITWISE OR ONFLOOR? with
the room property Visited?  So what we've done is this...

           Visited starts out set to 0
           ONFLOOR? is current 1

           (| 0 1)
           00000000
           00000001
           00000001   In otherwords Room 1 Visited? is now set to 1.

Now let's teleport to the attic (Floor 4) and do the same thing.

           Visited is now 1
           ONFLOOR? is now 4

           (| 1 4)
           00000001
           00000100
           00000101   Visited now set to decimal 5 (first and third bits set)

Our adventure now knows that our hero has been in this room as both the attic
and the basement but not in the main floor.  Now to determine whether to give
the long description or not what we do is BITWISE & ONFLOOR? with Visited.

Our hero enters the first room on the main floor.  First we check to see if
we've been here before.

           (& ONFLOOR? Visited)
           (& 2 5)
           00000010
           00000101
           00000000  Nope result is zero so we haven't been here.  Give the
                     long description then update Visited as we did above
                     in the basement and attic.   Room 1 Visited now set to
                     binary 00000111.  One bit set for each floor.

If we reenter Room 1 in the basement we then get...

           (& ONFLOOR? Visited)
           (& 1 7)
           00000001
           00000111
           00000001  Result not zero so we've been here before.  Give the short
                     description.

Now if we move to room 2, the process starts all over again.  We could visit
room 1, 2, 3 on floor 1 and room 2 and 4 on floor 2, etc and the game will track
each room using this simple method of bit twiddling the value of Visited? for
each room.  Remember, we only actually defined four rooms when we created the
adventure.  What we need to do is to use SETP to change the description of the
rooms as we move from floor to floor.  Perhaps you would code this into part of
the routine for UP and DOWN.  Each time we go up we multiply ONFLOOR? by 2
and each time we go down we divide ONFLOOR? by 2.  Now we will call a routine
to set the room descriptions.

          (cond
            ((= ONFLOOR? 1)
             (progn(setp ROOM1 $LDESC "You are in the northwest corner of
                                       the basement.")
                   (setp Room2 $LDESC "You are in the northeast corner of
                                       the basement.")
                   (setp Room3 $LDESC "You are in the southwest corner of
                                       the basement.")
                   (setp Room4 $LDESC "You are in the southeast corner of
                                       the basement.  It is not very well
                                       lit here.")))
            ((= ONFLOOR? 2)
             (progn(setp ROOM1 $LDESC "You are in the northwest corner of
                                       the main floor.")
                   (setp Room2 $LDESC "You are in the northeast corner of
                                       the main floor.")
                   (setp Room3 $LDESC "You are in the southwest corner of
                                       the main floor.")
                   (setp Room4 $LDESC "You are in the southeast corner of
                                       the main floor.  There is broken glass
                                       all over the floor.")))
            ((= ONFLOOR? 4)
             (progn(setp ROOM1 $LDESC "You are in the northwest corner of
                                       the attic. You notice a faint smell.")
                   (setp Room2 $LDESC "You are in the northeast corner of
                                       the attic.")
                   (setp Room3 $LDESC "You are in the southwest corner of
                                       the attic.")
                   (setp Room4 $LDESC "You are in the southeast corner of
                                       the attic.")))

It's actually pretty simple isn't it?  You can use SETP to change the properties
of any actor, object, room etc in the adventure.

You've probably guessed though, that if you put an object, let's say a basket
ball in ROOM2, that you would see it on all 3 floors.  You're right!  What we
need to do is to incorporate FLOORS into all parts of the ADVSYS runtime package
including CANSEE?, etc....  You will have to set ONFLOOR? for the basketball
then check to see if BASKETBALL ONFLOOR? equals ACTOR ONFLOOR?. 

Hope this helps you some.  Perhaps it will spark some new ideas.  Let's have
some feedback.  Floors and the judicious use of SETP should allow you to make
far more complex adventures than you ever thought possible using ADVSYS.


Bruce MacKay
Co-Author ELVES '87.
