-->

Sunday, December 8, 2013

CoCo, There's Still Time for You


Ahh, misspent youth. When I was a young man, I caught the bug. Computers. The Radio Shack in the mall put a TRS-80 Model III out in front of their store, and I was intrigued. Intrigue turned to passion, and passion turned into nerdly obsession, and I spent every hour I could standing there, playing with it, learning about it, writing programs in BASIC which I couldn’t save, and which would be gone the next time I could convince my parents to take me to the mall.

READY
>_

From there, I was hooked, and my obsession eventually became a career. My first computer was almost a Timex/Sinclair ZX-81, which I saved for all summer, mowing lawns in order to have the $99 that this wonderful little machine cost. At the end of the summer, my parents intervened, and, since it had the Good Housekeeping seal of approval (and the ZX-81 did not), I ended up with a Radio Shack TRS-80 Color Computer, instead - grey case, with 16K of memory on what was almost a reference implementation of the 6809E chipset.

I was thirteen.

Between the TRS-80s and the Burroughs mainframe running the CANDE OS (pronounced like "candy") with the VDTs and DecWriter printer terminals at the college where my dad was taking night classes, this was my introduction to computer science. I read every book I could in the college library – even the ones I didn’t understand. I learned about Pascal and LISP, BASIC and FORTRAN, Algol 68 and SNOBOL. I learned about the TRS-80 Color Computer. I memorized the memory map. I knew the PEEKs and POKEs. I became an expert on the hardware – and then I started hacking it. Primitive relay driven robotics projects, toy tanks with wires dangling out of them, wired to the PIA chip in the CoCo. Sensors and bad, poorly connected soldering. Memory upgrades. A floppy drive! No more finicky, unreliable tape backups. And in the end, many years later, a hard drive. 40 Megabytes worth of RLL driven storage, way more reliable than the floppies, thanks to a WD1002A-27X ISA hard drive controller, and an interface kit from Burke and Burke. More space than I would ever use.

I spend a lot of my time
doing things like this.
At the end of it all, I had quite the system. Running Microware OS-9, a multitasking operating system, I had a CGA monitor, a detached keyboard, a hard drive, floppy drives, a printer, and a DecWriter II (later a video terminal) running a secondary shell and login. Through the modem, I had access to the nascent internet through Delphi and CompuServe, and I could send emails to people around the world through the RiBBS BBS system.

Radio Shack, in the heyday of the TRS-80 line, controlled a large part of the home computer and business computer markets, but, eventually, the the IBM PC won. And, like many other computers and video games, my Color Computer ended up in boxes in the attic, full of hardware, cables,  slowly mouldering floppy drives -- and one 40 megabyte RLL hard drive, containing a file system not compatible with any modern system, accessible through hardware increasingly incompatible with modern PCs - or any other hardware. A hard drive containing the only copies some of the first programs I ever wrote, slowly deteriorating on largely inaccessible hardware.

The hard drive in question, with the Color Computer interface. The top board is a Western Digital ISA hard drive board, model WD1002A-27X. The small board underneath it is a Burke & Burke COCO XT board, which is an interface between ISA hard drive boards and the Color Computer expansion bus. Optionally, these came with a real time clock. Mine doesn't have that.


Over the years and decades, I had made some attempts to recover this, to move these files to modern hardware, before the inevitable happened, and the contents of that drive were lost forever.  Many challenges lay in that path, including no clear interface between the CoCo and a PC, no way to directly access the hard drive from modern equipment, and the fragility of the old equipment. In the end, the fragility became a major issue, and rescuing the data from the hard drive became a race for time, as simply accessing data on the disk would tend to corrupt it. There was one program in particular, an adventure game written in Pascal that I wrote, which I very much wanted a copy of. If I could get that file, I would consider the recovery effort to be a success.


A previous attempt at resurrecting the color computer. Here, I put the computer in a modern case with a multi-pak (expansion port). What ultimately doomed this attempt was signal degradation between the computer board and the multi-pak. The combination of multi-pak and computer board is too long to fit in pretty much any computer case, which prompted many attempts at rewiring. Some were more successful than others, but none proved to be 100% reliable.
The case for re-homing the
CoCo parts. Here, it is being
inspected for quality.
The CoCo board and a multi-pak board, re-homed in a modern PC case.
Another view. The nylon bolt is holding a daughterboard in place.
As long as there is no smoke or loud pops, everything is OK.
It works! ..sort of. The hard drive is in the second bay. While I could boot to the hard drive and read it, corruption of the directory structure happened rapidly in this configuration.

Recently, I attempted one more time to salvage these old floppies and the hard drive, and, this time, I succeeded. Here's how I did it, with notes on what worked for me, and what didn't.

 

Access to the hardware

 

Solving the monitor problem

Some of the first problems to solve were simply access to the hardware. The Color Computer uses RF output in an analog format (NTSC, PAL in other parts of the world), which is not compatible with modern televisions, for the most part. Fortunately, I do have an old analog television, just for problems like this, but, it's small, and, the CoCo has never had truly great output for televisions -- wavy lines and other interference are common. There are a couple of possibilities here, and I tried them both. First, I can convert the analog output to VGA using a converter. These converters proved to be a little difficult to find, but I managed to find a decent one on Amazon, which I used for a while. In the end the resolution wasn't there, and the output was a bit fuzzy -- good enough to play old video games, but not good enough for clear text.

The second possibility, at least on the CoCo III, is to use composite output. I have an old Apple ][ monitor, so, I tried this for a while, but, the output was never very crisp, especially at higher resolutions (such as when running OS-9 in 80 column mode), so in the end, eye fatigue did this solution in.

The third possibility, at least on more late model CoCos, is that there is a mostly-CGA-compatible port on the underneath of the machine, which can plug to the (mostly) proprietary CM8 monitor which was sold as an accessory to the CoCo. These monitors are hard to find, having not been made in several decades, but there are other, truly CGA compatible monitors that can be used (if you can find one), usually with a bit of level converting or other soldering involved. In the end, I did -- very luckily! -- score a CM8 monitor on eBay, and, in the end, this was the solution I went with for video output.

The Keyboard Problem

The second problem to conquer, hardware-wise, is the fact that there is not a detachable keyboard for the CoCo. In the past, what I have done to solve this is to find an older keyboard, and re-wire it so that the keys on the keyboard map to the IO matrix that the CoCo expects. This usually involves a lot of soldering, a rather thick cable between the keyboard and the computer, and an irrevocably  altered case. None of these were desirable, so, after a week or so of crouching on the ground typing on the old machine, I broke down and got a PS/2 keyboard interface from Cloud9. This allows me to plug a readily available, modern keyboard into the Color Computer. I had a mini keyboard in the style of the original IBM PC which I used. It's got real springs in the keys and makes some very satisfying, if somewhat loud, clacky sounds while typing. Between that and the coiled cable, it is very retro-awesome.

Rescuing the Files

In order to copy the files off of the floppies and on to something a little more reliable, I used another product from Cloud9, their SuperIDE interface. There are essentially two interfaces like this, one created by Cloud9, and the other put together by the Glenside Color Computer club -- who, incidentally, have been annually hosting the "last" CocoFest for over twenty years at this point. Because the Cloud9 interface supports NitrOS-9, and because NitrOS-9 and DriveWire integration is pretty tight (I used DriveWire later on in the process), I went with the SuperIDE interface. This interface allows me to hook up IDE devices to the CoCo, and access them like regular hard drives. In my case, I used a ZIP drive to do initial backups, and a compact flash card to do the initial booting into NitROS-9. I also used the compact flash to back up RSDOS (ie, native color computer) disks. HDB-DOS, an extension to Disk Extended Color BASIC (or, "DECB" for short), allows a CF card to look like 255 individually addressable floppies. For the first four floppy drives, a command allows you to switch back and forth between real floppy drives and the virtual ones, which allows you to copy between the physical drives and the CF card. After some long nights of babysitting the machine while changing floppies, accompanied by a database to track which slot had which virtual floppy, the easy part of copying the RS-DOS files was done.

This setup also allows for partitioning of a CF card (or other IDE device) to have two partitions -- one, RSDOS "floppies" as described above, and the other, an OS-9 partition. One of the emulated floppies serves as the boot floppy for the OS-9 system, and can be set to execute when the system powers on. This setup requires you to load a custom version of HDB-DOS into one of the ROM banks in the SuperIDE interface (The custom ROM image points to the correct offsets for the partitions), and creating an OS-9 boot floppy image suitable to your system, loaded into the correct "floppy" slot. Make backups, and make backups often! Use a scratch CF card, instead of one you might mind losing data on. Setting this up can be a little tricky, but is well worth the effort. Cloud9 can also set you up with a preformatted CF card, to save you the effort. Many thanks to Mark Marlette and Boisy Pitre over at Cloud9, who answered all my dumb questions and got me un-stuck on more than one occasion!


Access to OS-9

OS-9 proved to be slightly more difficult, especially as I was not to be satisfied by simply backing up the files into a safer medium than that which a dying hard drive provided. I wanted to get these files off of that hard drive, and accessible to a PC. Cloud9 offers a service for this, but I wanted to give it a go first, before admitting defeat. After many false starts, This is what I did:

1. Create a NitrOS-9 boot disk, and alter it to allow access to the old hard drive. RLL and MFM hard drives are not plug and play. Even on the PC, the user of these devices had to know things like the number of cylinders, sectors, the sector size, and the desired interleave factor to get them to work right. In the CoCo, same thing. For the Burke & Burke interface, and using OS-9, you create a driver description file (which uses a core driver module, provided here by B&B ages ago), which contains this information. These are hard to set up. In older versions of OS-9, the order of modules in the OS9Boot file matters, and they must be in contiguous sectors on the disk. Size matters, as well, and the entire process of creating a viable boot disk with a working boot file is very, very finicky. Fortunately, when I was young, I saw the danger of losing this information, once I got it right, and made many backups of the boot floppy. Like, a lot of backups. Ten, maybe twenty. The paranoia, as it turns out, was justified -- these 30 year old floppies started failing pretty regularly once I started accessing them again.

Fragile. So very fragile.

I fortunately had some floppies which were "new" -- never opened, never used (but still decades old). These also proved to be a little unreliable, but less so, and, mostly good enough. From here, with the same (arduous) process described above, I created a NitrOS-9 boot disk, and added in the old drivers. NitrOS-9 is a more modern implementation of OS-9, and is actively maintained (go here for the code base, and here for more information), so, the process is a bit easier these days, but it can still be touch and go. After a few tries, I had access to the old hard drive under NitrOS-9.

From here, make many, many backups of the boot floppy, and continue to the next step.

 
The boards plugged into the final system. From left to right: Floppy drive controller, SuperIDE interface, RS232 Pak, Bluetooth RS232 Pak emulator.

The ZIP drive and floppy drives. The ZIP drive is on the top.

2. Alter the boot disk so that it can talk to the Color Computer and some sort of modern hardware at the same time. Ideally, this would mean that the boot disk would be able to talk to a modern hard drive (a PATA/IDE drive, in my case, since I am using the SuperIDE interface. Interfaces for SCSI exist, as well), and the old RLL/COCO XT drive at the same time. Another very desirable feature would be to talk to a modern PC using something like DriveWire. Having this all at the same time would be ideal.

Unfortunately, it did not work out. I could get the combinations of (DriveWire + COCO XT) and (DriveWire + SuperIDE) to work, but not  (DriveWire + COCO XT + SuperIDE). The problem appears to be the undelying SuperIDE drivers and the COCO XT drivers interfering with each other. Most attempts with all three wouldn't even boot, and things like loading the other drivers (say, COCO XT) after successful boot would at best not be able to access their respective drives, and, at worst, immediately crash the system on loading the driver and device descriptors. Since my goal was not truly to have a system with all these at the same time, but rather to rescue old files, I resolved to use the two combinations, (DriveWire + COCO XT) and (DriveWire + SuperIDE), to do separate pieces of the work. Since I could have (DriveWire + SuperIDE), I used that to copy any OS-9 specific floppies I had over to my IDE drive (an IOMega ZIP drive, which worked out very well for this purpose), and, to rescue the files off the hard drive, I used the combination of (DriveWire + COCO XT). To copy the files using either configuration, I used the built-in OS-9 command, DSAVE, which basically issues a bunch of directory change and COPY commands, to copy each individual file. Depending on memory configuration, you may need to direct the DSAVE output to a file first, and then execute it. In OS-9, you can preload modules to make execution faster (for instance, you may preload and hold resident in memory the DIR, CHD and LIST commands). I found that I had to remove a lot of the modules I had preloaded in order to get DSAVE to not error out because of too little memory, even on a machine with a 512K expansion board (this is a LOT of memory for a Color Computer, considering the first iterations of the machine came with memory sizes such as 4K and 16K). There is another program available for the CoCo, named "ARC", which, for a lot of things, does a better job of copying directories and subdirectories, but, because of the state of the drive it was copying from, it didn't always work out. I found that the slow, plodding method that DSAVE takes to be more reliable in this situation. ARC, however, is a great tool. It, and a bunch of other really useful tools can be downloaded here.

Note- using the "ex" builtin, if you have Shell+ installed (standard on NitrOS-9), can reduce the memory problem I describe here. 

From here, the procedure was:
  • Start DriveWire on the PC
  • Ensure connectivity from the CoCo, usually by just doing a DIR on the remotely emulated drive
  • Start DSAVE on the CoCo, and monitor it. I would recommend getting a book and sitting there babysitting it, because, while reliable, there will from time to time be hiccups, and you'll need to restart it occasionally.

DriveWire

DriveWire is an application that runs on a PC, which allows access to the Color Computer. It can emulate hard drives through special drivers under OS-9, and even do things like allow the Color Computer to host web sites. Communication from the PC to the Color Computer is through the bitbanger serial port, which is the built in serial port on the back of the CoCo. It can also communicate with Color Computer emulators, such as the VCC Emulator created by Steve Bjork, via TCP/IP.

DriveWire 4, showing an emulated hard drive and two floppy drives.
 

After quite a few hours, the copy process was done. There were read errors on the old hard drive, as is to be expected, but I'd guess that about 90% of what was on there was successfully copied. At some future date, I may try to repair the hard drive sector by sector, but I don't actually have high hopes for that, since every read tends to corrupt it just a little bit more.

I did, however, find many cool things on that drive!

What I found on the hard drive

It's amazing, looking back in time to where I was about two decades ago. The last that this machine was heavily used was somewhere around 1992 to 1995.

Languages, Languages, Languages

I have always loved playing around with different computer languages. Aside from the standbys of C and Pascal (of which I have two versions each, from Microware and Frank Hogg Laboratories/DynaSoft), I also have compilers for languages such as LISP (xlisp in this case), LOGO (fun! this language can do a lot more than just turtle graphics!), and PILOT (a programming language for teachers, allowing them to create online lessons), and Basic09 (a cleaned up, Pascal-like version of BASIC made specifically for the OS-9 operating system).

Snapshot of life

There were also grocery lists, to do lists, old, low resolution GIFs, lists of phone numbers, and letters to an old girlfriend (Did she really used to call me that? How embarrassing.) There were also emails and posts from the Delphi and CompuServe systems (but not the missing archives, sorry), as well as emails sent across the RiBBs BBS system, and various online manuals. There were also copies of Tandy's productivity software, such as DeskMate and MultiVue, which is a windowing system for OS-9. MultiVue is still under active development. Latest versions, source code repository, and news can be found here.

An older version of MultiVue running on my CoCo, output to my TV. The drives are listed along the left side, with details in the middle. This is showing the top level directory for floppy drive 0, which is a bootable drive (note the os9boot file). MultiVue is capable of launching programs, managing windows, and so forth.


In the end, I did find a copy of the program that, for me, had become symbolic of this rescue effort, and the measure of success as to whether my rescue attempts, in the end, came through.

I was successful. I rescued it from the old, dying system, and now have many backups of it, and many other programs like it. Named ADVGAME.PAS, it is a youthful attempt at creating a text-based adventure game.

Here's the code:

PROGRAM SWAMP (INPUT,OUTPUT);
 (* THE SWAMP:
     AN ADVENTURE GAME
     FEATURING AN ENTIRE WORLD;
     YOU DO NOT HAVE TO DO THE 
     ADVENTURE, BUT IT IS THERE WHEN
     YOU ARE READY TO GO FIND IT. *)
 CONST XCOORD=0;           (* THESE ARE FOR THE *)
       YCOORD=1;           (* COORDINATES KEPT IN ARRAYS *)
       ZCOORD=2;
       SWALL=40;           (* SOUTHMOST SQUARE ON THE BOARD *)
       WWALL=40;           (* WESTMOST SQUARE*)
       BS=8;               (* BACKSPACE CHARACTER *)
       EOF=27;             (* END OF FILE CHARACTER *) 
       CR=13;              (* CARRIAGE RETURN CHARACTER *)
       MAXLOOSE=200;      (* MAX AMOUNT OF LOOSE OBJECTS *)
       MAXHELD=10;        (* MAX AMOUNT OF OWNED OBJECTS *)
       HIDDEN=0;          (* THESE ARE FOR THE ARRAY *)
       CLEAR=1;           (* NAMED 'VISIBILITY' *)
       BURIED=3;          (* SEE BELOW,IN THE 'VAR' SECTION *)

  TYPE LINE=ARRAY [0..255] OF CHAR;
       COMMANDS=(NOP,NORTH,SOUTH,EAST,WEST,
                 CHOP,BURY,DIG,
                 LOOK,DRINK,TAKE,MACHETE,
                 HIDE,JUNGLE,WEEDS,HANDS,
                 WOOD,STICKS,ROCK,GESTURE,
                 ALL,TREE,JUNK,
                 DECIPHER,EXAM,WATER,
                 EAT,BUGS,
                 DROP,INVENT,GUN,BOMB);
       (* ADDITIONS TO THE LIST OF COMMANDS WILL 
          CAUSE NEED FOR ALTERATION IN THE FOLLOWING 
          PROCEDURES/FUNCTIONS:
          PARSE,ACTION,   
          NAMEOFIT       *)

   VAR YOU:ARRAY[XCOORD..ZCOORD] OF INTEGER;       (*COORDINATES OF THE PLAYER ON THE FIELD *)
       UNDERSTOOD,         (* FLAG FOR WHETHER OR NOT THE LAST LINE *)
                           (* WAS UNDERSTOOD *)
       MOVEMENT,           (* WAS THERE MOVEMENT THIS TURN? *)
       HIDING,             (* WHETHER OR NOT PERSON IS HIDING *)
       GAMING:BOOLEAN;     (* FLAG FOR WHETHER OR NOT THE GAME WILL CONTINUE *)
       INLINE:LINE;        (* THE INPUT LINE *)
       HPOS:COMMANDS;      (* THE POSITION OF THE HANDS *)
       INPARSED:ARRAY[1..100] OF COMMANDS; (* THE PARSED INPUT LINE *)
       BACKSPACE:CHAR;     (* THE BACKSPACE CHAR *)
       WORD:INTEGER;       (* THE NUMBER OF WORDS *)
                           (* PARSED *)
       LOOP:INTEGER;       (*GENERAL PURPOSE LOOP VARIABLE *)
       HUNGER,             (* HUNGER OF PLAYER *)
       THIRST:INTEGER;     (* THIRST OF INDIVIDUAL *)
       FIELD:ARRAY[0..1600] OF CHAR;
                           (* THE PLAYING FIELD *)
                           (* ARRAYTOP FOR FIELD MUST EQUAL 
                             SWALL*WWALL *)
       SPECIAL:ARRAY [1..100] OF INTEGER;
                           (* SEE THE PROCEDURE 'DESCSP' *)
                           (* IN 'DESCRIBE' *)
       LOOSESTUFF:ARRAY[1..MAXLOOSE] OF COMMANDS; (* STUFF LYING AROUND *)
       VISIBILITY,         (* VISIBILITY OF THE LOOSE STUFF *)
       LOCATION:ARRAY [1..MAXLOOSE] OF INTEGER; (* LOCATIONS OF LOOSESTUFF *)
       STUFF:ARRAY[1..MAXHELD] OF COMMANDS; (* STUFF HELD BY PLAYER *)



  FUNCTION UNCOORD(X,Y:INTEGER):INTEGER;
   (* THIS FUNCTION CONVERTS X,Y COORDINATES TO ONE

      DIMENSIONAL COORDINATES ON A LINE WHICH
      IS THE LENGTH OF SWALL TIMES WWALL.
      IN OTHER WORDS,THE FIELD. *)
   BEGIN (* UNCOORD *)
    UNCOORD:=(Y*WWALL)+X;
   END;  (* UNCOORD *)



 (* THE FUNCTIONS N,S,E, AND W
    ARE FOR MOVEMENT OF THE PLAYER ACROSS THE BOARD
    N:NORTH
    S:SOUTH
    E:EAST
    W:WEST       *)

 FUNCTION N(I:INTEGER):INTEGER;
  BEGIN
   I:=I-1;
   IF I<0 data-blogger-escaped-begin="" data-blogger-escaped-end="" data-blogger-escaped-function="" data-blogger-escaped-i:="I+1;" data-blogger-escaped-i="" data-blogger-escaped-if="" data-blogger-escaped-movement:="TRUE;" data-blogger-escaped-n:="I;" data-blogger-escaped-s="" data-blogger-escaped-then="">SWALL THEN I:=SWALL;
   S:=I;
   MOVEMENT:=TRUE;
  END;



 FUNCTION E(I:INTEGER):INTEGER;
  BEGIN
   E:=N(I);
   MOVEMENT:=TRUE;
  END;



 FUNCTION W(I:INTEGER):INTEGER;
  BEGIN
   I:=I+1;
   IF I>WWALL THEN I:=WWALL;
   W:=I;
   MOVEMENT:=TRUE;
  END;

 (* THE FOLLOWING COMMANDS ARE FOR 
     PROCESSING CERTIAN COMMANDS,SUCH AS
      INVENTORY,TAKE,DROP,ET CETERA.
     SOME OF THESE COMMANDS WILL NOT BE USED VERY
     MANY TIMES IN THE PROGRAM,AND,IN FACT,
     SOME OF THEM WILL BE USED ONLY AT ONE
     SPOT. NEVERTHELESS,THEY ARE PRESENTED AS FUNCTIONS
     TO INCREASE THE PROGRAM'S MODULARITY AND TO INCREASE READABILITY. *)

 PROCEDURE NAMEOFIT(WHICH:COMMANDS);
  (* WRITES OUT THE NAME OF A COMMAND *)
   BEGIN (* NAMEOFIT *)
    CASE WHICH OF 
     GUN:WRITE(' GUN ');
     MACHETE:WRITE(' MACHETE ');
     DRINK:WRITE(' DRINK ');
     NORTH:WRITE(' NORTH ');
     STICKS:WRITE(' BUNCH OF STICKS ');
     HANDS:WRITE(' HANDS ');
     BUGS:WRITE(' BUGS ');
     ROCK:WRITE(' ROCK ');
     WOOD:WRITE(' PIECE OF WOOD');
     SOUTH:WRITE(' SOUTH ');
     EAST:WRITE(' EAST ');
     WEST:WRITE(' WEST ');
     DROP:WRITE(' DROP ');
     TAKE:WRITE(' TAKE ');
     BOMB:WRITE(' BOMB ')
    END; (* CASE OF WHICH *)
   END; (* NAMEOFIT *)


 FUNCTION HAVE(WHAT:COMMANDS):BOOLEAN;
  (* DOES THE PLAYER HAVE A CETIAN ITEM? *)
  VAR I:INTEGER;
  BEGIN (* HAVE *)
   HAVE:=FALSE;
   FOR I:=1 TO MAXHELD DO
    IF STUFF[I]=WHAT THEN HAVE:=TRUE;
  END; (* HAVE *)



 FUNCTION HERE(WHAT:COMMANDS):BOOLEAN;
  (* IS A CERTIAN ITEM LYING ABOUT?
     ALSO:
      IT MUST BE IN PLAIN SIGHT *)
  VAR I:INTEGER;
      PLACE:CHAR;
  BEGIN (* HERE *)
   HERE:=FALSE;
   FOR I:=1 TO MAXLOOSE DO
    IF (LOCATION[I]=UNCOORD(YOU[XCOORD],YOU[YCOORD])) AND
       (VISIBILITY[I]=CLEAR) AND
       (LOOSESTUFF[I]=WHAT) THEN 
        HERE:=TRUE;
   IF HAVE(WHAT) THEN HERE:=TRUE;
   PLACE:=FIELD[UNCOORD(YOU[XCOORD],YOU[YCOORD])];
   CASE WHAT OF
    JUNGLE:IF PLACE='J' THEN HERE:=TRUE;
    WEEDS:IF PLACE='U' THEN HERE:=TRUE;
    TREE:IF PLACE='T' THEN HERE:=TRUE;
    WATER:IF PLACE='W' THEN HERE:=TRUE
   END; (* CASE OF WHAT *)
  END; (* HERE *)


 PROCEDURE MAKEOBJECT(WHAT:COMMAND;XY:INTEGER);
  VAR I:INTEGER;
      MADE:BOOLEAN;        (* WAS AN OBJECT MADE? *)
   BEGIN (* MAKEOBJECT *)
    I:=0;
    MADE:=FALSE;
    REPEAT
     I:=I+1;
     IF LOOSESTUFF[I]=NOP THEN
      BEGIN
       LOOSESTUFF[I]:=WHAT;
       LOCATION[I]:=XY;
       MADE:=TRUE;
      END;
     UNTIL (MADE) OR (I>MAXLOSE);
    END; (* MAKEOBJECT *)



 PROCEDURE OWN(WHAT:COMMANDS);
  VAR I,J:INTEGER;         (* LOOP VARIABLE *)
      OWNERSHIP:BOOLEAN;       (* SUCCESSFUL OR NOT ? *)
  BEGIN (* OWN *)
   OWNERSHIP:=FALSE;
   J:=1;
   REPEAT
    IF (LOCATION[J]=UNCOORD(YOU[XCOORD],YOU[YCOORD])) AND
       (LOOSESTUFF[J]=WHAT) AND
       (VISIBILITY[J]<>BURIED) THEN
     BEGIN
      I:=1;
      REPEAT 
       IF STUFF[I]=NOP THEN
        BEGIN
         OWNERSHIP:=TRUE;
         STUFF[I]:=WHAT;
         LOCATION[J]:=(-1);
         LOOSESTUFF[J]:=NOP;
         VISIBILITY[J]:=CLEAR;
        END;
       I:=I+1;
      UNTIL (OWNERSHIP) OR (I>=MAXHELD);
     END;
    J:=J+1;
   UNTIL (J>=MAXLOOSE) OR (OWNERSHIP);
   IF (HERE(JUNGLE)) AND (WHAT=BUGS) THEN 
    BEGIN
     WRITELN('THEY CRAWL OUT OF YOUR HANDS BEFORE YOU CAN REALLY GRAB THEM.');
     OWNERSHIP:=TRUE;
    END;
   IF NOT OWNERSHIP THEN
    IF NOT HAVE(NOP) THEN 
        WRITELN('YOU ARE CARRYING TOO MUCH STUFF')
     ELSE 
      BEGIN
       WRITE('WHAT ');
       NAMEOFIT(WHAT);
       WRITELN('?');
      END
    ELSE WRITELN('GOT IT.');
  END; (* OWN *)


 PROCEDURE DISOWN(WHICH:COMMAND);
  VAR I:INTEGER;
      DROPPED:BOOLEAN;
  BEGIN (* DISOWN *)
   IF WHICH=ALL THEN
    BEGIN
     WRITELN('YOU DROP EVERYTHING.');
     FOR I:=1 TO MAXHELD DO
      IF STUFF[I]<>NOP THEN DISOWN(STUFF[I]);
    END
    ELSE
   IF WHICH<>NOP THEN
    BEGIN (* IF *)
     I:=0;
     DROPPED:=FALSE;
     REPEAT
      I:=I+1;
      IF STUFF[I]=WHICH THEN
       BEGIN
        STUFF[I]:=NOP;
        MAKEOBJECT(WHICH,UNCOORD(YOU[XCOORD],YOU[YCOORD]));
        DROPPED:=TRUE;
       END;
     UNTIL (DROPPED) OR (I>MAXHELD);
     IF NOT DROPPED THEN WRITELN('YOU DONT HAVE ONE.');
    END (* IF *)
   ELSE WRITELN('YOU HAVE TO TELL ME WHAT TO DROP');
  END; (* DISOWN *)


 PROCEDURE CONCEAL(WHAT:COMMANDS;HOW:INTEGER);
  (* PLEASE NOTE:
      IF AN OBJECT IS NOT HIDEABLE IT 
      WILL BECOME VISIBLE IN THE NEXT TURN *)
  VAR I:INTEGER;           (* LOOP VARIABLE *)
      OK:BOOLEAN;
  BEGIN (* CONCEAL *)
   IF WHAT=ALL THEN 
    BEGIN
     FOR I:=1 TO MAXHELD DO
      IF STUFF[I]<>NOP THEN CONCEAL(STUFF[I],HOW);
    END;
   OK:=FALSE;
   IF (WHAT=NOP) AND (HOW<>BURIED) THEN
    CASE FIELD[UNCOORD(YOU[XCOORD],YOU[YCOORD])] OF
     'J','U':BEGIN
              HIDING:=TRUE;
              OK:=TRUE;
              WRITELN('YOU ARE HIDDEN.');
             END
     OTHERWISE WRITELN('YOU CANT HIDE HERE.')
    END (* CASE OF PLAYER'S LOCATION *)
   ELSE IF HAVE(WHAT) THEN 
    BEGIN (* IF *)
     DISOWN(WHAT);
     I:=0;
     REPEAT
      IF (LOCATION[I]=UNCOORD(YOU[XCOORD],YOU[YCOORD])) AND
       (LOOSESTUFF[I]=WHAT) THEN
       BEGIN
        VISIBILITY[I]:=HOW;
        OK:=TRUE;
       END;
      I:=I+1;
     UNTIL (OK) OR (I>MAXLOOSE);
     IF OK THEN
      BEGIN
       WRITE('IT IS ');
       CASE HOW OF
        BURIED:WRITELN('BURIED');
        HIDDEN:WRITELN('HIDDEN')
       END;
      END
      ELSE WRITELN('YOU DONT HAVE ONE.');
    END; (* IF *)
  END; (* CONCEAL *)


 PROCEDURE UNEARTH;
  VAR I:INTEGER;           (* LOOP VAR *)
  BEGIN (* UNEARTH *)
   FOR I:=1 TO MAXLOOSE DO
    IF LOCATION[I]=UNCOORD(YOU[XCOORD],YOU[YCOORD]) THEN
     BEGIN (* IF *)
      CASE VISIBILITY[I] OF
       HIDDEN:BEGIN
               WRITE('IN YOUR SCUFFLING ABOUT YOU FOUND A');
               NAMEOFIT(LOOSESTUFF[I]);
               WRITELN('.');
              END;
       BURIED:BEGIN
               WRITE('YOU DUG UP A');
               NAMEOFIT(LOOSESTUFF[I]);
               WRITELN('.');
              END
      END; (* CASE OF VISIBILITY *);
      VISIBILITY[I]:=CLEAR;
     END (* IF *);
    END; (* UNEARTH *)

 PROCEDURE MOW(X,Y:INTEGER;TOOL:COMMANDS);
  (* X AND Y ARE THE LOCATION ON THE GRID CHANGE IS
     TO TAKE PLACE;
     TOOL IS THE OBJECT TO BE USED *)
  VAR PLACE:CHAR;          (* PLAYER'S LOCATION IN CHAR FORM *)
     CHANGE:CHAR;         (* WHATEVER IT IS TO BE CHANGED TO *)
  BEGIN
   PLACE:=FIELD[UNCOORD(X,Y)];
   CASE PLACE OF 
    'J':BEGIN
         IF TOOL=MACHETE THEN CHANGE:='U';
         IF TOOL=BOMB THEN CHANGE:='B';
        END;
    'U':BEGIN
         IF TOOL=MACHETE THEN CHANGE:='C';
         IF TOOL=BOMB THEN CHANGE:='B';
         MAKEOBJECT(STICKS,UNCOORD(X,Y));
        END;
    'C':IF TOOL=BOMB THEN CHANGE:='R';
    'R':IF TOOL=BOMB THEN 
         BEGIN
          CHANGE:='R';
          MAKEOBJECT(ROCK,UNCOORD(X,Y));
         END;
    'T':BEGIN
         IF TOOL=BOMB THEN CHANGE:='B';
         IF TOOL=MACHETE THEN CHANGE:='C';
         MAKEOBJECT(WOOD,UNCOORD(X,Y));
        END
    OTHERWISE CHANGE:=PLACE
   END; (* CASE OF PLACE *)
   IF PLACE=CHANGE THEN WRITELN('YOU CANT DO THAT');
   FIELD[UNCOORD(X,Y)]:=CHANGE;
  END; (* CHANGE *)


  PROCEDURE ANNIHILATE(WHAT:COMMANDS);
   (* ANNIHILATES SOMETHING OF THE PLAYER'S POSSESSION *)
   VAR I:INTEGER;
       ZAPPED:BOOLEAN;
   BEGIN (* ANNIHILATE *)
    IF HAVE(WHAT) THEN 
     I:=0;
     ZAPPED:=FALSE;
     REPEAT
      I:=I+1;
      IF STUFF[I]=WHAT THEN
       BEGIN
        ZAPPED:=TRUE;
        STUFF[I]:=NOP;
       END;
     UNTIL (ZAPPED) OR (I>MAXHELD);
   END;


 PROCEDURE SCRAWLINGS(WHAT,MODE:COMMANDS);
  (* IF ANY MARKINGS ARE ON THE OBJECT 'WHAT',
     THIS PROCEDURE WILL TELL OF THEM *)
  BEGIN (* SCRAWLINGS *)
   IF HERE(WHAT) THEN
    CASE MODE OF
     DECIPHER:CASE WHAT OF
           MACHETE:WRITELN('"SEARS,ROEBUCK, & CO."');
           WOOD:BEGIN
                 WRITELN('"DO NOT REMOVE THIS TAG UNDER PENALTY OF LAW"');
                 WRITELN('(ASK A STUPID QUESTION...)');
                END;
           JUNGLE:BEGIN
                   WRITELN('"INGREDIENTS:');
                   WRITELN(' ENRICHED WHEAT FLOUR,');
                   WRITELN(' ANIMAL AND VEGETABLE SHORTENING');
                   WRITELN('  ALL NATURAL FLAVORS"');
                  END;
           BUGS:WRITELN('"PATENT PENDING"');
           BOMB:WRITELN('"!!BOMB EXPLODES ON IMPACT!!"')
          OTHERWISE WRITELN('NOTHING WRITTEN ON IT.')
          END; (* CASE OF WHAT *)
      EXAM:CASE WHAT OF
            WOOD:WRITELN('LOOKS LIKE ORDINARY WOOD TO ME.');
            STICKS:WRITELN('LOOKS LIKE THEY WERE CHOPPED FROM SOME UNDERBRUSH.');
            ROCK:WRITELN('LOOKS LIKE YOU COULD BELT SOMEONE GOOD WITH IT.');
            MACHETE:WRITELN('IT HAS SOMETHING WRITTEN ON IT.');
            JUNGLE:WRITELN('BUGS EVERYWHERE,MAN!');
            BOMB:WRITELN('LOOKS LIKE A BOMB')
           OTHERWISE WRITELN('NOTHING OUT OF THE ORDINARY.')
           END (* CASE OF WHAT *)
     END (* CASE OF MODE *)
   ELSE
    BEGIN
     WRITE('I DONT SEE ANY');
     NAMEOFIT(WHAT);
     WRITELN('.');
    END;
  END; (* SCRAWLINGS *)


 (* THIS IS THE END OF THE SPECIAL COMMAND SECTION *)


 PROCEDURE MAP(NUM:INTEGER);
  VAR I,J:INTEGER;         (* LOOP VARIABLE *)
  BEGIN (* MAP *)
   CASE NUM OF 
    1:BEGIN
       FOR J:=1 TO SWALL*WWALL DO
         FIELD[J]:='J';
       FIELD[UNCOORD(15,20)]:='T';
       FIELD[UNCOORD(10,10)]:='W';
       FIELD[UNCOORD(40,10)]:='W';
       FIELD[UNCOORD(40,20)]:='W';
       FIELD[UNCOORD(15,20)]:='W';
       FIELD[UNCOORD(15,15)]:='W';
       FOR I:=10 TO 15 DO
        FOR J:=10 TO 15 DO
         FIELD[UNCOORD(I,J)]:='W';
       FIELD[UNCOORD(14,14)]:='T';
       SPECIAL[2]:=UNCOORD(14,14);
       FIELD[UNCOORD(10,10)]:='U';
       FIELD[UNCOORD(15,15)]:='U';
       FOR J:=10 TO 20 DO
        FIELD[UNCOORD(12,J)]:='W';
      VISIBILITY[1]:=HIDDEN;
      LOOSESTUFF[1]:=MACHETE;
      LOCATION[1]:=UNCOORD(WWALL DIV 2,SWALL DIV 2);
      SPECIAL[1]:=UNCOORD(WWALL DIV 2,SWALL DIV 2);
      END;
   10:BEGIN (* NO OPERATION *) END
   END;
  END; (* MAP *)



 FUNCTION COM(WHICH:COMMANDS;WDS:INTEGER):INTEGER;
  BEGIN (* COM *)
   INPARSED[WDS]:=WHICH;
   IF WDS<98 data-blogger-escaped-100:begin="" data-blogger-escaped-100="" data-blogger-escaped-2:case="" data-blogger-escaped-2:if="" data-blogger-escaped-2="" data-blogger-escaped-3:case="" data-blogger-escaped-4:case="" data-blogger-escaped-4="" data-blogger-escaped-5="" data-blogger-escaped-a="" data-blogger-escaped-about="" data-blogger-escaped-actual="" data-blogger-escaped-all="" data-blogger-escaped-amount="" data-blogger-escaped-and="" data-blogger-escaped-anything="" data-blogger-escaped-are="" data-blogger-escaped-area="" data-blogger-escaped-arraytop="" data-blogger-escaped-be="" data-blogger-escaped-begin="" data-blogger-escaped-being="" data-blogger-escaped-blanks="" data-blogger-escaped-by="" data-blogger-escaped-carving="" data-blogger-escaped-case="" data-blogger-escaped-char="" data-blogger-escaped-chars="" data-blogger-escaped-checks="" data-blogger-escaped-clearing="" data-blogger-escaped-com:="WDS+1;" data-blogger-escaped-com="" data-blogger-escaped-comes="" data-blogger-escaped-compiled="" data-blogger-escaped-compute="" data-blogger-escaped-coordinates="" data-blogger-escaped-currently="" data-blogger-escaped-describe="" data-blogger-escaped-described="" data-blogger-escaped-describes="" data-blogger-escaped-descsp="" data-blogger-escaped-do="" data-blogger-escaped-east="" data-blogger-escaped-end="" data-blogger-escaped-eol="" data-blogger-escaped-eplace:="FIELD[UNCOORD(X,E(Y))];" data-blogger-escaped-eplace="WHAT" data-blogger-escaped-field="" data-blogger-escaped-for="" data-blogger-escaped-form="" data-blogger-escaped-function="" data-blogger-escaped-goes="" data-blogger-escaped-growth="" data-blogger-escaped-how="" data-blogger-escaped-i:="1" data-blogger-escaped-i:integer="" data-blogger-escaped-i="" data-blogger-escaped-if="" data-blogger-escaped-in="" data-blogger-escaped-inline="" data-blogger-escaped-inparsed="" data-blogger-escaped-is="" data-blogger-escaped-it="" data-blogger-escaped-j:="1" data-blogger-escaped-j:integer="" data-blogger-escaped-j="" data-blogger-escaped-jungle="" data-blogger-escaped-junkhere="" data-blogger-escaped-l:="1" data-blogger-escaped-l="" data-blogger-escaped-len:="2" data-blogger-escaped-len="" data-blogger-escaped-length="" data-blogger-escaped-lenloop="" data-blogger-escaped-less="" data-blogger-escaped-livingston="" data-blogger-escaped-location="" data-blogger-escaped-long="" data-blogger-escaped-loop="" data-blogger-escaped-maxloose="" data-blogger-escaped-needed="" data-blogger-escaped-neplace:="FIELD[UNCOORD(N(X),E(Y))];" data-blogger-escaped-neplace="WHAT" data-blogger-escaped-no="" data-blogger-escaped-north="" data-blogger-escaped-northeast="" data-blogger-escaped-northwest="" data-blogger-escaped-note="" data-blogger-escaped-nplace:="FIELD[UNCOORD(N(X),Y)];" data-blogger-escaped-nplace="WHAT" data-blogger-escaped-number="" data-blogger-escaped-nwplace:="FIELD[UNCOORD(N(X),W(Y))];" data-blogger-escaped-nwplace:char="" data-blogger-escaped-nwplace="WHAT" data-blogger-escaped-of="" data-blogger-escaped-on="" data-blogger-escaped-one="" data-blogger-escaped-op="" data-blogger-escaped-operation="" data-blogger-escaped-or="" data-blogger-escaped-out="" data-blogger-escaped-parse:="WDS;" data-blogger-escaped-parse:integer="" data-blogger-escaped-parse="" data-blogger-escaped-parsed="" data-blogger-escaped-path="" data-blogger-escaped-place:char="" data-blogger-escaped-place="" data-blogger-escaped-please="" data-blogger-escaped-pointer="" data-blogger-escaped-prints="" data-blogger-escaped-procedure="" data-blogger-escaped-reads="" data-blogger-escaped-remains="" data-blogger-escaped-represented="" data-blogger-escaped-returns="" data-blogger-escaped-rocky="" data-blogger-escaped-scanned="" data-blogger-escaped-see="" data-blogger-escaped-seplace:="FIELD[UNCOORD(S(X),E(Y))];" data-blogger-escaped-seplace="WHAT" data-blogger-escaped-smouldering="" data-blogger-escaped-so="" data-blogger-escaped-some="" data-blogger-escaped-south="" data-blogger-escaped-southeast="" data-blogger-escaped-southwest="" data-blogger-escaped-special="" data-blogger-escaped-specialx="" data-blogger-escaped-splace:="FIELD[UNCOORD(S(X),Y)];" data-blogger-escaped-splace="WHAT" data-blogger-escaped-statement="" data-blogger-escaped-surround="" data-blogger-escaped-swplace:="FIELD[UNCOORD(S(X),W(Y))];" data-blogger-escaped-swplace="WHAT" data-blogger-escaped-tests="" data-blogger-escaped-than="" data-blogger-escaped-that="" data-blogger-escaped-the="" data-blogger-escaped-then="" data-blogger-escaped-to="" data-blogger-escaped-tree="" data-blogger-escaped-value="" data-blogger-escaped-var="" data-blogger-escaped-variable="" data-blogger-escaped-variables="" data-blogger-escaped-way="" data-blogger-escaped-wds:="COM(WATER,WDS);" data-blogger-escaped-wds="" data-blogger-escaped-west="" data-blogger-escaped-what="" data-blogger-escaped-where="" data-blogger-escaped-word="" data-blogger-escaped-words="" data-blogger-escaped-wordval:="WORDVAL+INLINE[J];" data-blogger-escaped-wordval="" data-blogger-escaped-wplace:="FIELD[UNCOORD(X,W(Y))];" data-blogger-escaped-wplace="WHAT" data-blogger-escaped-write="" data-blogger-escaped-writeln="" data-blogger-escaped-x="" data-blogger-escaped-y="" data-blogger-escaped-your:="">NOP) AND
        (VISIBILITY[I]=CLEAR) THEN
      BEGIN
       WRITE('I SEE A');
       NAMEOFIT(LOOSESTUFF[I]);
       WRITELN('.');
      END;
    END; (* JUNKHERE *)


  BEGIN (* DESCRIBE *)
   PLACE:=FIELD[UNCOORD(X,Y)];
   CASE PLACE OF
     'J':WRITELN('YOU ARE IN A THICK JUNGLE');
     'U':WRITELN('YOU ARE IN SOME THICK UNDERGROWTH');
     'C':WRITELN('YOU ARE IN A CLEARING');
     'T':WRITELN('YOU ARE UNDER A TREE');
     'R':WRITELN('YOU ARE IN A VERY ROCKY AREA');
     'W':WRITELN('YOU ARE ON WATER');
     'B':BEGIN
          WRITELN('YOU ARE IN THE SMOULDERING RUINS OF');
          WRITELN('SOME JUNGLE GROWTH');
         END
   END; (* CASE OF PLACE *)
   IF PLACE='J' THEN
    WRITELN('YOU CANT SEE TOO FAR IN ANY DIRECTION')
   ELSE SURROUND;
   DESCSP(X,Y);
   JUNKHERE;
  END; (* DESCRIBE *)



 PROCEDURE ACTION(WDS:INTEGER);
     VAR I,J,K:INTEGER;    (* LOOP VARIABLES *)
      OWNERSHIP:BOOLEAN;   (* USED BY SOME OF THE ROUTINES *)
  BEGIN (* ACTION *)
   FOR I:=1 TO WDS DO
    CASE INPARSED[I] OF 
     NORTH:YOU[XCOORD]:=N(YOU[XCOORD]);
     SOUTH:YOU[XCOORD]:=S(YOU[XCOORD]);
     EAST:YOU[YCOORD]:=E(YOU[YCOORD]);
     WEST:YOU[YCOORD]:=W(YOU[YCOORD]);
     LOOK:MOVEMENT:=TRUE;
     GESTURE:CASE INPARSED[I+1] OF
              NORTH,
              SOUTH,
              EAST,
              WEST:BEGIN
                     HPOS:=INPARSED[I+1];
                     WRITE('YOUR HANDS INDICATE THE');
                     NAMEOFIT(INPARSED[I+1]);
                     I:=I+1;
                   END
             OTHERWISE 
              BEGIN
               HPOS:=INPARSED[I+1];
               WRITELN('YOUR HANDS INDICATE THE');
               NAMEOFIT(INPARSED[I+1]);
              END
             END; (* CASE IF INPARSED[I+1] *)
     HIDE:CONCEAL(INPARSED[I+1],HIDDEN);
     BURY:CONCEAL(INPARSED[I+1],BURIED);
     DIG:UNEARTH;
     DECIPHER:SCRAWLINGS(INPARSED[I+1],DECIPHER);
     EXAM:SCRAWLINGS(INPARSED[I+1],EXAM);
     EAT:BEGIN
         CASE INPARSED[I+1] OF
          BOMB:WRITELN('YEAH. RIGHT.');
          BUGS:IF HERE(JUNGLE) THEN
                BEGIN
                 WRITELN('');
                 HUNGER:=HUNGER+11;
                END;
          MACHETE:WRITELN('I ABSOLUTELY REFUSE TO EAT A MACHETE.');
          ROCK:WRITELN('YOU HAVE WIERD CULINARY TASTES.');
          NOP:WRITELN('EAT WHAT?')
          OTHERWISE WRITELN('THAT ISNT EDIBLE')
         END; (* CASE OF INPARSED *)
        END; (* EAT *)
     CHOP:BEGIN (* CHOP *)
           IF HAVE(MACHETE) THEN 
            CASE INPARSED[I+1] OF
             NOP,          (* IF UNSPECIFIED *)
             JUNGLE,
             WEEDS,
             TREE:MOW(YOU[XCOORD],YOU[YCOORD],MACHETE);
             STICKS:IF HAVE(STICKS) THEN WRITELN('NOW THEY ARE SHORTER.');
             WOOD:IF HAVE(WOOD) THEN
                   BEGIN
                    ANNIHILATE(WOOD);
                    MAKEOBJECT(STICKS,UNCOORD(YOU[XCOORD],YOU[YCOORD]));
                   END;
             GUN:IF HAVE(GUN) THEN
                  BEGIN
                   ANNIHILATE(GUN);
                   MAKEOBJECT(JUNK,UNCOORD(YOU[XCOORD],YOU[YCOORD]));
                  END
             OTHERWISE WRITELN('YOU CANT CUT THAT.');
            END (* CASE OF INPARSED[I+1] *)
          ELSE WRITELN('YOU DONT HAVE THE CORRECT TOOL.');
         END; (* CHOP *)
     TAKE:OWN(INPARSED[I+1]);
     DROP:DISOWN(INPARSED[I+1]);
     INVENT:BEGIN
                OWNERSHIP:=FALSE;
                WRITELN('YOU HAVE:');
                FOR J:=1 TO MAXHELD DO
                 IF STUFF[J]<>NOP THEN
                  BEGIN (* IF *)
                   OWNERSHIP:=TRUE;
                   NAMEOFIT(STUFF[J]);
                  END; (* IF *)
                WRITELN;
                IF NOT OWNERSHIP THEN WRITELN('NOTHING.');
          END;

     DRINK:IF HERE(WATER) THEN
            BEGIN
             THIRST:=THIRST+4;
             CASE THIRST OF
              1,2,3,4,5:WRITELN('AH! AH... REFRSHING! AHHH...');
              6,7,8,9,10:WRITELN('STILL A LITTLE THIRSTY,THOUGH.');
              11,12,13,14,15,16:WRITELN('MY! THAT WAS GOOD.');
              16,17,18,19,20:WRITELN('NOT BAD.')
              OTHERWISE WRITELN('YOU FEEL A BIT WATERLOGGED.')
             END; (* CASE OF THIRST *)
            END
           ELSE WRITELN('DRINK WHAT?');
     NOP: BEGIN (* NO OPERATION *) END
    END; (* CASE OF INPARSED[I] *)
   IF WDS>1 THEN UNDERSTOOD:=TRUE;
  END; (* ACTION *)




 BEGIN (* SWAMP *)
  BACKSPACE:=BS; (* SO IT'S A PRINTABLE CHAR *)
  FOR LOOP:=1 TO MAXHELD DO
   STUFF[LOOP]:=NOP;
  FOR LOOP:=1 TO MAXLOOSE DO
   BEGIN
    LOOSESTUFF[LOOP]:=NOP;
    LOCATION[LOOP]:=(-1);
   END;
  MAP(1);
  HUNGER:=40;
  THIRST:=40;
  GAMING:=TRUE;
  HIDING:=FALSE;
  YOU[XCOORD]:=WWALL DIV 2;
  YOU[YCOORD]:=SWALL DIV 2;
  YOU[ZCOORD]:=0;
  DESCRIBE(YOU[XCOORD],YOU[YCOORD]);
  REPEAT
   FOR LOOP:=1 TO 100 DO  (* CLEAR OUT INLINE *)
    INLINE[LOOP]:=' ';
   (* BEGIN READ INLINE *)
    LOOP:=1;
    WRITE('#'); (* PROMPT *)
    REPEAT
     LOOP:=LOOP+1;
     READ(INLINE[LOOP]);
     IF LOOP<1 data-blogger-escaped-anyhow="" data-blogger-escaped-be="" data-blogger-escaped-because="" data-blogger-escaped-boundary="" data-blogger-escaped-check="" data-blogger-escaped-going="" data-blogger-escaped-if="" data-blogger-escaped-incremented="" data-blogger-escaped-inline="" data-blogger-escaped-is="" data-blogger-escaped-it="" data-blogger-escaped-loop:="LOOP-2;" data-blogger-escaped-then="" data-blogger-escaped-to="" data-blogger-escaped-two="" data-blogger-escaped-until="">99) OR (INLINE[LOOP]=CR);
   IF LOOP<98 data-blogger-escaped--100:writeln="" data-blogger-escaped--110:writeln="" data-blogger-escaped--20:writeln="" data-blogger-escaped--40="" data-blogger-escaped-0:writeln="" data-blogger-escaped-10:writeln="" data-blogger-escaped-1:writeln="" data-blogger-escaped-5:writeln="" data-blogger-escaped-a="" data-blogger-escaped-action="" data-blogger-escaped-almost="" data-blogger-escaped-and="" data-blogger-escaped-are="" data-blogger-escaped-begin="" data-blogger-escaped-case="" data-blogger-escaped-constricting="" data-blogger-escaped-death="" data-blogger-escaped-describe="" data-blogger-escaped-died="" data-blogger-escaped-double="" data-blogger-escaped-end.="" data-blogger-escaped-end="" data-blogger-escaped-food="" data-blogger-escaped-from="" data-blogger-escaped-gaming:="FALSE;" data-blogger-escaped-gaming="" data-blogger-escaped-getting="" data-blogger-escaped-have="" data-blogger-escaped-having="" data-blogger-escaped-hidden.="" data-blogger-escaped-hiding:="FALSE;" data-blogger-escaped-hiding="" data-blogger-escaped-hunger:="HUNGER-1;" data-blogger-escaped-hunger="" data-blogger-escaped-hungry.="" data-blogger-escaped-if="" data-blogger-escaped-inline="" data-blogger-escaped-intestines="" data-blogger-escaped-lack="" data-blogger-escaped-longer="" data-blogger-escaped-loop:="LOOP+1;" data-blogger-escaped-movement:="FALSE;" data-blogger-escaped-movement="" data-blogger-escaped-near="" data-blogger-escaped-no="" data-blogger-escaped-not="" data-blogger-escaped-nourishment.="" data-blogger-escaped-of="" data-blogger-escaped-pang="" data-blogger-escaped-pangs.="" data-blogger-escaped-pre="" data-blogger-escaped-read="" data-blogger-escaped-severe="" data-blogger-escaped-swamp="" data-blogger-escaped-then="" data-blogger-escaped-thirst.="" data-blogger-escaped-thirst:="THIRST-1;" data-blogger-escaped-thirst="" data-blogger-escaped-thirsty="" data-blogger-escaped-unconcious="" data-blogger-escaped-understood:="FALSE;" data-blogger-escaped-understood="" data-blogger-escaped-until="" data-blogger-escaped-up="" data-blogger-escaped-weak="" data-blogger-escaped-word:="PARSE;" data-blogger-escaped-writeln="">
Note: DynaSoft Pascal does not have a string data type.

And there it is  -- rescued from my dimming earlier years, an attempt at a world, an exposition of self taught, budding skills. Time has passed, the hardware no longer relevant, the software relevant to nobody but me. But I had to reach back, through the unrelenting waters of time, and grasp for one distant yet limpid memory, and rekindle that link to my own personal past.

I won. I got it. I made that link. And thirteen? Distancing and ever fading thirteen..  Thirteen, I'm all right with you.



(disclosure: although I mentioned Cloud-9 a bit in this post, I am not an employee, shareholder, etc. I just use their stuff :-) )