[comp.sources.amiga] v89i095: wanderer - the game v2.2, Part02/03

page%rishathra@Sun.COM (Bob Page) (04/26/89)

Submitted-by: mab@druwy.att.com (Alan Bland)
Posting-number: Volume 89, Issue 95
Archive-name: fun/wand22.2

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	ami-pw.menus.h
#	ami-pw.palette.h
#	ami-sounds.c
#	ami-sounds.h
#	display.c
#	edit.c
#	encrypt.c
#	fall.c
#	game.c
# This is archive 2 of a 3-part kit.
# This archive created: Tue Apr 25 00:28:06 1989
echo "extracting ami-pw.menus.h"
sed 's/^X//' << \SHAR_EOF > ami-pw.menus.h
X
Xstruct IntuiText IText1 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Instructions        HELP",
X	NULL
X};
X
Xstruct MenuItem MenuItem5 = {
X	NULL,
X	0,36,
X	192,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText1,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText2 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Show map            F10",
X	NULL
X};
X
Xstruct MenuItem MenuItem4 = {
X	&MenuItem5,
X	0,27,
X	192,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText2,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText3 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Move to center      F3",
X	NULL
X};
X
Xstruct MenuItem MenuItem3 = {
X	&MenuItem4,
X	0,18,
X	192,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText3,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText4 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Toggle map mode     F2",
X	NULL
X};
X
Xstruct MenuItem MenuItem2 = {
X	&MenuItem3,
X	0,9,
X	192,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText4,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText5 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Jump to next level  F1",
X	NULL
X};
X
Xstruct MenuItem MenuItem1 = {
X	&MenuItem2,
X	0,0,
X	192,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText5,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct Menu Menu2 = {
X	NULL,
X	82,0,
X	66,0,
X	MENUENABLED,
X	"Wander",
X	&MenuItem1
X};
X
Xstruct IntuiText IText6 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Quit Game       q",
X	NULL
X};
X
Xstruct MenuItem MenuItem11 = {
X	NULL,
X	0,45,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText6,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText7 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Credits         c",
X	NULL
X};
X
Xstruct MenuItem MenuItem10 = {
X	&MenuItem11,
X	0,36,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText7,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText8 = {
X	3,1,JAM1,
X	0,0,
X	NULL,
X	"",
X	NULL
X};
X
Xstruct MenuItem SubItem6 = {
X	NULL,
X	161,32,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText8,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText9 = {
X	9,1,JAM1,
X	0,0,
X	NULL,
X	"Edit an existing screen:  wanderer -e screenfilename",
X	NULL
X};
X
Xstruct MenuItem SubItem5 = {
X	&SubItem6,
X	161,24,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText9,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText10 = {
X	9,1,JAM1,
X	0,0,
X	NULL,
X	"    Create a new screen:  wanderer -e",
X	NULL
X};
X
Xstruct MenuItem SubItem4 = {
X	&SubItem5,
X	161,16,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText10,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText11 = {
X	3,1,JAM1,
X	0,0,
X	NULL,
X	"",
X	NULL
X};
X
Xstruct MenuItem SubItem3 = {
X	&SubItem4,
X	161,8,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText11,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText12 = {
X	3,1,JAM1,
X	0,0,
X	NULL,
X	"from the CLI as follows:",
X	NULL
X};
X
Xstruct MenuItem SubItem2 = {
X	&SubItem3,
X	161,0,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText12,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText13 = {
X	3,1,JAM1,
X	0,0,
X	NULL,
X	"To edit a screen, exit the game and run wanderer",
X	NULL
X};
X
Xstruct MenuItem SubItem1 = {
X	&SubItem2,
X	161,-8,
X	416,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP+HIGHBOX,
X	0,
X	(APTR)&IText13,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText14 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Edit Screen",
X	NULL
X};
X
Xstruct MenuItem MenuItem9 = {
X	&MenuItem10,
X	0,27,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText14,
X	NULL,
X	NULL,
X	&SubItem1,
X	MENUNULL
X};
X
Xstruct IntuiText IText15 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Restore Game    F7",
X	NULL
X};
X
Xstruct MenuItem MenuItem8 = {
X	&MenuItem9,
X	0,18,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText15,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText16 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Save Game       F6",
X	NULL
X};
X
Xstruct MenuItem MenuItem7 = {
X	&MenuItem8,
X	0,9,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText16,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct IntuiText IText17 = {
X	3,1,COMPLEMENT,
X	0,0,
X	NULL,
X	"Redraw Screen  shift-W",
X	NULL
X};
X
Xstruct MenuItem MenuItem6 = {
X	&MenuItem7,
X	0,0,
X	176,8,
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,
X	0,
X	(APTR)&IText17,
X	NULL,
X	NULL,
X	NULL,
X	MENUNULL
X};
X
Xstruct Menu Menu1 = {
X	&Menu2,
X	0,0,
X	75,0,
X	MENUENABLED,
X	"Project",
X	&MenuItem6
X};
X
X#define MenuList1 Menu1
SHAR_EOF
echo "extracting ami-pw.palette.h"
sed 's/^X//' << \SHAR_EOF > ami-pw.palette.h
X
XUSHORT Palette[] = {
X	0x0000,	/* color #0 */
X	0x0ECA,	/* color #1 */
X	0x0C00,	/* color #2 */
X	0x0E22,	/* color #3 */
X	0x0E77,	/* color #4 */
X	0x0070,	/* color #5 */
X	0x0090,	/* color #6 */
X	0x00B0,	/* color #7 */
X	0x0DC0,	/* color #8 */
X	0x035F,	/* color #9 */
X	0x07AF,	/* color #10 */
X	0x0F60,	/* color #11 */
X	0x0A60,	/* color #12 */
X	0x0BBB,	/* color #13 */
X	0x0888,	/* color #14 */
X	0x0444	/* color #15 */
X#define PaletteColorCount 16
X};
X
X#define PALETTE Palette
SHAR_EOF
echo "extracting ami-sounds.c"
sed 's/^X//' << \SHAR_EOF > ami-sounds.c
X#ifdef AMIGA
X
X/****************************   Sound.c   *********************************
X
X    Sound is copyright (c) 1988 by Richard Lee Stockton, 21305 60th Ave W.,
XMountlake Terrace, Washington 98043, 206/776-1253(voice), but may be freely
Xdistributed as long as no profit is made from its distribution or sale
Xwithout my written permission. I call this concept 'FreeWare', you can
Xcall it whatcha want.
X
XHacked to death by Alan Bland, bears little resemblance to the original
Xsound.c.
X
X**************************************************************************/
X
X#include <exec/types.h>
X#include <exec/memory.h>
X#include <libraries/dosextens.h>
X#include <devices/audio.h>
X#include <string.h>
X#include "sounds.h"
X
X/* We'll need 4 buffers in CHIP memory, all else in FAST, if ya got it */
X
X#define  BUFSIZE  1024L
X
X/* This array defines all the possible sounds */
X
Xstruct SoundData {
X	long	sps;
X	BOOL	stereo;
X	long	sactual;
X	char	*sbuffer;
X} sdata[MAX_SOUNDS];
X
Xstruct IOAudio	*sound[4]={NULL,NULL,NULL,NULL};
XUBYTE	sunit[4]={12,10,5,3};
Xlong	templength;
Xchar	*tempbuffer=NULL, *cbuf[4]={NULL,NULL,NULL,NULL};
X
X/*********** quit, give-up, go home, finish... Neatness counts! ******/
X
Xvoid freeSounds(string)
Xchar    *string;
X{
X   short   k;
X
X   if(sound[0])      /* This cleans up the audio device stuff */
X   {
X      for(k=3;k>(-1);k--)    if(sound[k]) AbortIO(sound[k]);
X      if(sound[0]->ioa_Request.io_Device) CloseDevice(sound[0]);
X      for(k=3;k>(-1);k--)
X      {
X         if(sound[k]->ioa_Request.io_Message.mn_ReplyPort)
X            DeletePort(sound[k]->ioa_Request.io_Message.mn_ReplyPort);
X      }
X      for(k=3;k>(-1);k--)
X      {
X         if(sound[k]) FreeMem(sound[k],(long)sizeof(struct IOAudio));
X         if(cbuf[k])  FreeMem(cbuf[k],BUFSIZE);
X      }
X      sound[0]=NULL;
X   }
X
X  if (string != NULL)
X  {
X	fatal(string);
X  }
X
X/* Get rid of all the sound data */
X   for(k=0; k<MAX_SOUNDS; k++)
X   {
X	if (sdata[k].sbuffer)
X	    FreeMem(sdata[k].sbuffer, sdata[k].sactual);
X   }
X
X/* Clean up everything else */
X
X   if(tempbuffer)          FreeMem(tempbuffer,templength);
X
X/* and return, caller will exit */
X}
X
X
X/*  Don't Allocate if Low Mem - by Bryce Nesbitt  */
X/* Aberations by RLS. 4096 should be fudge enough */
X
Xchar *SafeAllocMem(size,flags)
Xlong size, flags;
X{
X   register char *p;
X   
X   if(p=(char *)AllocMem(size,flags))
X      if(AvailMem(MEMF_CHIP)<4096L)
X         { FreeMem(p,size);  return(NULL); }
X   return(p);
X}
X
X
X/******** Load SoundFile 'sPath' ********/
X
Xvoid loadSound(sPath, sd)
Xchar    *sPath;
Xstruct SoundData *sd;
X{
X   struct FileHandle    *sFile=NULL;
X   struct FileInfoBlock *finfo=NULL;
X   struct FileLock      *lock=NULL;
X          long          i, j, sstart;
X          char          string[5];
X
X/* Set defaults if not found in IFF file */
X   sd->stereo = FALSE;
X   sd->sactual = 0L;
X
X/* Allocate 256 bytes as work memory */
X
X   if(!(tempbuffer=SafeAllocMem(256L,MEMF_CLEAR|MEMF_PUBLIC)))
X        freeSounds("No Work Memory!");
X
X/* Check for and parse IFF data in first 256 bytes of file */
X
X   if(!(sFile=(struct FileHandle *)Open(sPath,MODE_OLDFILE)))
X   {
X/*
X      char errmsg[80];
X      templength=256L;
X      strcpy(errmsg, "Can't open ");
X      strcat(errmsg, sPath);
X      freeSounds(errmsg);
X*/
X      /* ignore if sound file not found */
X      sd->sbuffer = NULL;
X      FreeMem(tempbuffer,256L); tempbuffer=NULL;
X      return;
X   }
X   Read(sFile,tempbuffer,256L);              /* load the 1st 256 bytes */
X   for(sstart=0L, sd->sps=0L, i=0L; i<252L; i+=4L)
X   {
X      strncpy(string,tempbuffer+i,4);   string[4]=NULL;
X      if(!(strcmp(string,"VHDR")))        /* get samples per second */
X      {
X         for(j=0;j<(long)((UBYTE)tempbuffer[i+20]);j++) sd->sps+=256L;
X         sd->sps += ((UBYTE)tempbuffer[i+21L]);
X      }
X      if(!(strcmp(string,"CHAN")))            /* Channel Assignment */
X      {
X         if((tempbuffer[i+7]==6)||(tempbuffer[i+11]==6)) sd->stereo=TRUE;
X      }
X      if(!(strcmp(string,"BODY")))        /* get size of sound data */
X      {
X         for(j=0;j<4;j++) sd->sactual+=(((UBYTE)tempbuffer[i+7L-j])<<(8*j));
X         sstart = i+8L; i=252L;
X      }
X   }
X
X/* if not in IFF format, get filesize from FileInfoBlock */
X
X   if(!sd->sactual)
X   {
X
X/* Allocate a file info block, get size from it, and de-allocate */
X
X      if((!(finfo=(struct FileInfoBlock *)
X         SafeAllocMem((long)sizeof(struct FileInfoBlock),MEMF_CLEAR)))
X       ||(!(lock=(struct FileLock *)Lock(sPath,ACCESS_READ)))||(!(Examine(lock,finfo))) )
X                    freeSounds("FileInfoBlock Problem!");
X      sd->sactual = finfo->fib_Size;      if(lock) UnLock(lock);
X      if(finfo) FreeMem(finfo,(long)sizeof(struct FileInfoBlock));
X
X/* default for non-IFF sample */
X      sd->sps = 20000L;
X   }
X
X/* clean up work area */
X
X   FreeMem(tempbuffer,256L); tempbuffer=NULL;
X
X/* Allocate _contiguous_ memory for SOUND data. */
X/* We'll transfer in BUFSIZE chunks to CHIP memory a little later. */
X/* We have to do the contiguity(?) check since AllocMem() does not. */
X
X   if((AvailMem(MEMF_LARGEST) < sd->sactual) ||
X     (!(sd->sbuffer=SafeAllocMem(sd->sactual,MEMF_CLEAR|MEMF_PUBLIC))))
X        { Close(sFile); freeSounds("Need Contiguous Memory!"); }
X
X/* Load the data into sbuffer */
X
X   Seek(sFile,sstart,OFFSET_BEGINNING);
X   if((Read(sFile,sd->sbuffer,sd->sactual)) == -1L)
X      { Close(sFile); freeSounds("Read Error!");}
X   Close(sFile);
X}
X
Xvoid initSoundMem()
X{
X    short  k;
X
X/* Allocate sound data buffers from CHIP memory. Ports and */
X/* Audio Request Structures do NOT require CHIP memory */
X
X   for(k=0;k<4;k++)
X   {
X     if(!(cbuf[k]=SafeAllocMem(BUFSIZE,
X           MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC))) freeSounds("No CHIP Memory!");
X     if(!(sound[k]=(struct IOAudio *)SafeAllocMem((long)sizeof(struct IOAudio),
X                     MEMF_CLEAR|MEMF_PUBLIC))) freeSounds("No IOA Memory!");
X   }
X   if( (!(sound[0]->ioa_Request.io_Message.mn_ReplyPort =
X           (struct MsgPort *) CreatePort("Sound0",0L))) ||
X       (!(sound[1]->ioa_Request.io_Message.mn_ReplyPort =
X           (struct MsgPort *) CreatePort("Sound1",0L))) ||
X       (!(sound[2]->ioa_Request.io_Message.mn_ReplyPort =
X           (struct MsgPort *) CreatePort("Sound2",0L))) ||
X       (!(sound[3]->ioa_Request.io_Message.mn_ReplyPort =
X           (struct MsgPort *) CreatePort("Sound3",0L))) )
X		freeSounds("No Port Memory!");
X   
X
X/* Open Audio using the first IOAudio as the 'initializer' request */
X
X   sound[0]->ioa_Request.io_Message.mn_Node.ln_Pri = 20;
X   sound[0]->ioa_Data   = &sunit[0];
X   sound[0]->ioa_Length = 4L;
X   if((OpenDevice(AUDIONAME,0L,sound[0],0L))!=NULL)
X      freeSounds("No Audio Device!");
X
X/* Set all IOAudios. */
X
X   for(k=0;k<4;k++)
X   {
X      sound[k]->ioa_Request.io_Message.mn_Node.ln_Pri = 20;
X      sound[k]->ioa_Request.io_Command = CMD_WRITE;
X      sound[k]->ioa_Request.io_Flags   = ADIOF_PERVOL;
X
X/* Note copies of Device & AllocKey from initializer. */
X
X      sound[k]->ioa_Request.io_Device  = sound[0]->ioa_Request.io_Device;
X      sound[k]->ioa_AllocKey  = sound[0]->ioa_AllocKey;
X
X/* Each IOAudio has its own CHIP buffer, Port, and Unit (left/right) */
X
X      sound[k]->ioa_Data   = (UBYTE *)cbuf[k];
X
X/* One time through this BUFSIZE (or smaller) part of the whole */
X
X      sound[k]->ioa_Cycles = 1L;
X   }
X
X/* The compiler wants 'Unit' to be a structure, we just want to mask */
X/* into the allocated left/right channels. left=1 or 8, right=2 or 4 */
X/*        ...zap! You're a Unit structure! Feel any different?       */
X
X   for(k=2;k>(-1);k-=2)
X   {
X      sound[k+1]->ioa_Request.io_Unit = (struct Unit *)
X                      ((ULONG)(sound[0]->ioa_Request.io_Unit)&6L);
X      sound[k]->ioa_Request.io_Unit  = (struct Unit *)
X                      ((ULONG)(sound[0]->ioa_Request.io_Unit)&9L);
X   }
X
X}
X
X/*****************  make a noise ******************/
X
Xvoid playSound(snum)
Xint snum;
X{
X    LONG    dactual, dlength, remaining;
X    USHORT  count;
X    short   k;
X    long    cycles = 1;
X
X/* don't do sound if not loaded */
X    if (sdata[snum].sbuffer == NULL) return;
X
X    for (k=0; k<4; k++)
X    {
X
X/* 3579547 divided by 55 = 65083, nearly the maximum Period (65535) */
X
X      sound[k]->ioa_Period = 3579547L/sdata[snum].sps;
X
X/* As LOUD as possible. Use your monitor/stereo volume. Rock 'n Roll! */
X
X      sound[k]->ioa_Volume = 64L;
X    }
X
X/* If in STEREO, split file. If in MONO, 'b' buffers use 'a' data */
X
X   if(sdata[snum].stereo) remaining=(sdata[snum].sactual/2L)-(sdata[snum].sactual&1L);
X   else
X   {
X      remaining=sdata[snum].sactual;
X      sound[1]->ioa_Data   = (UBYTE *)cbuf[0];
X      sound[3]->ioa_Data   = (UBYTE *)cbuf[2];
X   }
X
X/* dactual is the length of one channel's complete data */
X
X   dactual=remaining;     k=count=0;
X
X/* we be doing loops here */
X
X   do
X   {
X
X/* be CERTAIN ioa_Length is an even number & set datalength */
X
X      if(remaining>BUFSIZE) dlength=BUFSIZE;
X       else  { dlength=remaining;  dlength-=(dlength&1L); }
X
X/* Move the data into the proper CHIP buffer of BUFSIZE */
X
X      movmem(sdata[snum].sbuffer+(dactual-remaining),cbuf[k],(int)dlength);
X
X/* Don't load or use the right CHIP buffers if MONO. Saves time. */
X
X      if(sdata[snum].stereo) movmem(sdata[snum].sbuffer+(sdata[snum].sactual-remaining),
X                        cbuf[k+1],(int)dlength);
X
X/* Data has been moved, so adjust 'remaining' */
X
X      remaining-=dlength;
X
X/* Left and Right Lengths are the same, no matter what! */
X
X      sound[k]->ioa_Length = sound[k+1]->ioa_Length = dlength;
X
X/* Start one set of Left/Right Channels. */
X      BeginIO(sound[k]);      BeginIO(sound[k+1]);
X
X/* Is this the last time AND the last cycle? If yes & no, reset. */
X
X      if(remaining<2L) if(--cycles!=0L)
X         { remaining=dactual;   dlength=BUFSIZE; }
X
X/* Is this the last time, or what? */
X
X      if(remaining<2L)  WaitIO(sound[k+1]);   /* wait for LAST request */
X      else
X      {
X         if(k) k=0; else k=2;    /* switch buffers & wait for PREVIOUS */
X         if(count++)  WaitIO(sound[k+1]);
X      }
X
X/* Keep going until we run out of data */
X
X   } while(remaining>1L);                   /* End of Loop */
X}
X
X/******** initialize everything ********/
X
Xvoid initSounds()
X{
X
X/* Load 'em up! */
X
X    loadSound("sounds/death",	&sdata[DEATH_SOUND]);
X    loadSound("sounds/arrow",	&sdata[ARROW_SOUND]);
X    loadSound("sounds/boulder",	&sdata[BOULDER_SOUND]);
X    loadSound("sounds/clock",	&sdata[CLOCK_SOUND]);
X    loadSound("sounds/diamond",	&sdata[DIAMOND_SOUND]);
X    loadSound("sounds/deadmonster", &sdata[DEADMONSTER_SOUND]);
X    loadSound("sounds/kaboom",	&sdata[KABOOM_SOUND]);
X    loadSound("sounds/exit",	&sdata[EXIT_SOUND]);
X    loadSound("sounds/teleport",&sdata[TELEPORT_SOUND]);
X    loadSound("sounds/munch",	&sdata[MUNCH_SOUND]);
X    loadSound("sounds/step",	&sdata[STEP_SOUND]);
X    loadSound("sounds/cage",	&sdata[CAGE_SOUND]);
X    loadSound("sounds/push",	&sdata[PUSH_SOUND]);
X
X/* Setup chip buffers and I/O structures */
X
X    initSoundMem();
X}
X
X#endif
SHAR_EOF
echo "extracting ami-sounds.h"
sed 's/^X//' << \SHAR_EOF > ami-sounds.h
X#ifdef AMIGA
X
X#define DEATH_SOUND	0
X#define ARROW_SOUND	1
X#define BOULDER_SOUND	2
X#define CLOCK_SOUND	3
X#define DIAMOND_SOUND	4
X#define DEADMONSTER_SOUND	5
X#define KABOOM_SOUND	6
X#define EXIT_SOUND	7
X#define TELEPORT_SOUND	8
X#define MUNCH_SOUND	9
X#define STEP_SOUND	10
X#define CAGE_SOUND	11
X#define PUSH_SOUND	12
X#define MAX_SOUNDS	13	/* one higher than last one */
X
X#endif
SHAR_EOF
echo "extracting display.c"
sed 's/^X//' << \SHAR_EOF > display.c
X#include "wand_head.h"
X
Xextern int debug_disp;
X
X/* This function is used to draw a symbol on the map, and when running
X * in full-screen display mode.  Added by Alan Bland for the AMIGA to
X * allow the map characters to use a color graphics font.
X */
Xvoid draw_map_symbol(ch)
Xint ch;
X{
X#ifdef AMIGA
X	int color;
X	switch (ch)
X	{
X	case 'M':	color = BLUE;		break;
X	case 'S':	color = ORANGE;		break;
X	case ' ':	color = DK_GREEN;	break;
X	case '#':	color = DK_GRAY;	break;
X	case '<':	color = ORANGE;		break;
X	case '>':	color = ORANGE;		break;
X	case 'O':	color = DK_GRAY;	break;
X	case ':':	color = BROWN;		break;
X	case '/':	color = BROWN;		break;
X	case '\\':	color = BROWN;		break;
X	case '*':	color = WHITE;		break;
X	case '=':	color = DK_GRAY;	break;
X	case '@':	color = RED;		break;
X	case 'T':	color = YELLOW;		break;
X	case 'X':	color = RED;		break;
X	case '!':	color = BLACK;		break;
X	case 'C':	color = LT_GRAY;	break;
X	case '+':	color = LT_BLUE;	break;
X	case 'A':	color = RED;		break;
X	case '^':	color = ORANGE;		break;
X	default:	ch='?';color = DK_GRAY;	break;
X	}
X	set_map_font(1);
X	setcolor(color, DK_GREEN);
X	addch(ch);
X	setcolor(TEXT_COLOR, BACK_COLOR);
X	set_map_font(0);
X#else
X	addch(ch);
X#endif
X}
X
X/* draw a box at the specified row,column,width,height */
Xvoid draw_box(r,c,w,h)
Xint r,c,w,h;
X{
X#ifdef AMIGA
X	/* white rectangle with dark green interior */
X	/* note: coordinates are text coords, must adjust for graphics */
X	int x1=c*8+8;
X	int y1=r*8+8;
X	int x2=x1+(w-2)*8;
X	int y2=y1+(h-2)*8;
X
X	SetAPen(R, DK_GREEN);
X	RectFill(R, x1, y1, x2, y2);
X	SetAPen(R, WHITE);
X	Move(R, x1-1, y1-1);
X	Draw(R, x1-1, y2+1);
X	Draw(R, x2+1, y2+1);
X	Draw(R, x2+1, y1-1);
X	Draw(R, x1-1, y1-1);
X
X	SetAPen(R, TEXT_COLOR);
X#else
X	char buf1[80], buf2[80];
X	int x,y;
X	buf1[0] = '+';
X	buf2[0] = '|';
X	for (x=1;x<w-1;++x) {
X		buf1[x] = '-';
X		buf2[x] = ' ';
X	}
X	buf1[x] = '+';
X	buf2[x] = '|';
X	buf1[x+1] = '\0';
X	buf2[x+1] = '\0';
X
X	move(r,c);
X	addstr(buf1);
X	for (y=1;y<h-1;++y) {
X		move(r+y,c);
X		addstr(buf2);
X	}
X	move(r+h-1,c);
X	addstr(buf1);
X#endif
X}
X
Xvoid map(row_ptr)
Xchar (*row_ptr)[ROWLEN+1];
X{
Xint  x,y;
Xint  ch;
Xdraw_box(0,0,ROWLEN+2,NOOFROWS+2);
Xfor(y = 0;y < NOOFROWS; y++)
X    {
X    for(x = 0; x < ROWLEN; x++)
X	{
X	ch = (*row_ptr)[x];
X	if(!debug_disp)
X	    {
X	    if((ch == 'M')||(ch == 'S'))
X		ch = ' ';
X	    }
X	else
X	    {
X            if( !(ch==' '||ch=='#'||ch=='<'||ch=='>'||ch=='O'||ch==':'||
X	          ch=='/'||ch=='\\'||ch=='*'||ch=='='||ch=='@'||ch=='T'||
X	          ch=='X'||ch=='!'||ch=='M'||ch=='S'||ch=='C'||ch=='+'||
X                  ch=='A'||ch=='^') )
X		ch = '"';
X	    }
X	/* don't bother drawing spaces - speeds up non-smart curses */
X	if (ch != ' ')
X	    {
X	    move(y+1,x+1);
X	    draw_map_symbol(ch);
X	    }
X	}
X    row_ptr++;
X    }
Xif(!debug_disp)
X    {
X    move(18,0);
X    addstr("Press any key to return to the game.");
X    refresh();
X    (void) getchar();
X    for(y=0;y<=(NOOFROWS+2);y++)
X        {
X        move(y,0);
X	addstr("                                            ");
X	}
X    }
Xelse
X    refresh();
X}
X
X/* called by scroll() and display() to actually draw the game display */
Xvoid rdisplay(cx,cy,row_ptr,score)
Xchar (*row_ptr)[ROWLEN+1];
Xint  cx,cy,score;
X{
X    int  x,y = 0,
X         x_coord,y_coord;
X    char ch;
X    while(y<(cy-3))
X    {
X        y++;
X        row_ptr++;
X    };
X    for(y=(cy-3);y<=(cy+3);y++)
X    {
X        y_coord = (y+3-cy)*2;
X        if ((y<0) || (y>=NOOFROWS))
X        {
X#ifdef AMIGA
X	    /* this makes sure graphics are done right */
X	    int i, ax;
X	    for (ax=0,i=0; i<11; ax+=3,++i)
X		{
X		    draw_symbol(ax,y_coord,'#');
X		}
X#else
X            move(y_coord+1,1);
X            addstr("#################################");
X            move(y_coord+2,1);
X            addstr("#################################");
X#endif
X        }
X        else
X	{
X            for(x=(cx-5);x<=(cx+5);x++)
X            {
X                x_coord = (x+5-cx)*3;
X                if ((x<0) || (x>ROWLEN-1))
X                    draw_symbol(x_coord,y_coord,'#');
X                else
X                {
X                    ch = (*row_ptr)[x];
X                    draw_symbol(x_coord,y_coord,ch);
X                }
X            };
X	    row_ptr++;
X        }                   /*   end if   */
X    }                       /* end y loop */
X    move(16,0);
X    refresh();
X}
X
X/* draw the game display, doing intelligent scrolling if possible */
X/* actually, all this does is draw the display contents without */
X/* erasing the previous contents or redrawing the border */
X/* (looks better on machines that don't have intelligent curses) */
X/* should be possible to do nifty scrolling routines here at some point */
Xvoid scroll(cx,cy,row_ptr,score)
Xchar (*row_ptr)[ROWLEN+1];
Xint  cx,cy,score;
X{
X    /* assume border is there, just draw game display contents */
X    rdisplay(cx,cy,row_ptr,score);
X}
X
X/* draw the game display, erasing the current contents first */
Xvoid display(cx,cy,row_ptr,score)
Xchar (*row_ptr)[ROWLEN+1];
Xint  cx,cy,score;
X{
X    /* draw the border and erase current contents of display region */
X    draw_box(0,0,35,16);
X    /* now do the actual display */
X    rdisplay(cx,cy,row_ptr,score);
X}
X
Xvoid redraw_screen(maxmoves,num,score,nf,diamonds,mx,sx,sy,frow)
Xint maxmoves,num,score,nf,diamonds,mx,sx,sy;
Xchar **frow;
X{
Xchar buffer[50];
Xclear();
Xmove(0,48);
X(void) addstr("Score\t   Diamonds");
Xmove(1,48);
X(void) addstr("\tFound\tTotal");
Xmove(3,48);
X(void) sprintf(buffer,"%d\t %d\t %d  ",score,nf,diamonds);
X(void) addstr(buffer);
Xmove(6,48);
X(void) sprintf(buffer,"Current screen %d",num);
X(void) addstr(buffer);
Xif(maxmoves != 0)
X(void) sprintf(buffer,"Moves remaining = %d   ",maxmoves);
Xelse
X{
X    (void) strcpy(buffer,"     Unlimited moves     ");
X    maxmoves = -1;
X};
Xmove(15,48);
X(void) addstr(buffer);
Xshow_monster(mx != -1);           /* tell player if monster exists */
X
Xif(!debug_disp)
X    display(sx,sy,frow,score);
Xelse
X    map(frow);
X}
SHAR_EOF
echo "extracting edit.c"
sed 's/^X//' << \SHAR_EOF > edit.c
X#include "wand_head.h"
X
Xextern char *playscreen();
X
Xextern int debug_disp;
Xextern char *edit_screen;
Xextern char screen[NOOFROWS][ROWLEN+1];
X
Xstatic char *inst[] = { "O   Boulder",
X			"< > Arrows",
X			"^   Balloon",
X			":   Earth",
X			"!   Landmine",
X			"*   Treasure",
X			"/ \\ Deflectors",
X			"+   Cage",
X			"= # Rock",
X			"T   Teleport",
X			"A   Arrival (1 max)",
X			"X   Exit (always 1)",
X			"@   Start (always 1)",
X			"M   Big Monster (1 max)",
X			"S   Baby Monster",
X			"-   Alternative space",
X			"C   Time Capsule",
X			NULL };
X/* Print instructions around the screen */
Xvoid instruct()
X{
Xint loop;
Xfor(loop = 0; inst[loop] ; loop++)
X    {
X    move(loop+1,55);
X    addstr(inst[loop]);
X    }
Xmove(20,0);
Xaddstr("Use wanderer keys to move. m = change no. of moves, p = play game\n");
Xaddstr("n = play game with full screen, q = quit, x = quit without save.");
X}
X
Xvoid noins()
X{
Xint loop;
Xfor(loop =0; inst[loop] ; loop++)
X    {
X    move(loop+1,55);
X    addstr("                       ");
X    }
Xmove(20,0);
Xaddstr("                                                                            \n");
Xaddstr("                                                                            ");
X}
X
X/* Actual edit function */
X
Xvoid editscreen(num,score,bell,maxmoves,keys)
Xint  num, maxmoves,
X     *bell,
X     *score;
Xchar keys[10];
X{
Xint  x,y,sx=0,sy=0,quit=0,nx,ny,nosave =0;
Xchar (*frow)[ROWLEN+1] = screen,
X     ch;
Xchar buffer[50];
Xchar *howdead;
X
Xfor(x=0;x<=ROWLEN;x++)
X    for(y=0;y<NOOFROWS;y++)
X	{
X        if(screen[y][x] == '@')
X	    {
X	    sx = x;
X	    sy = y;
X	    }
X        if(screen[y][x] == '-')
X        	screen[y][x] = ' ';
X        };
Xx=sx;
Xy=sy;
Xif(maxmoves != 0)
X(void) sprintf(buffer,"Moves remaining = %d   ",maxmoves);
Xelse
X(void) strcpy(buffer,"     Unlimited moves     ");
Xdebug_disp=1;
Xmap(frow);
Xmove(18,0);
Xaddstr(buffer);
X
X/* ACTUAL EDIT FUNCTION */
X
Xinstruct();
Xwhile(!quit)
X{
Xmove(y+1,x+1);
Xrefresh();
Xcursor(1);
Xch = (char)getchar();
Xcursor(0);
X
Xnx=x;
Xny=y;
X
Xif(ch == keys[3]||ch == keys[2]||ch == keys[1]||ch == keys[0])
X    {
X    if(ch == keys[3])
X	    nx++;
X    if(ch == keys[2])
X	    nx--;
X    if(ch == keys[1])
X	    ny++;
X    if(ch == keys[0])
X            ny--;
X    }
Xelse if(ch == 'q')
X    {
X    noins();
X    break;
X    }
Xelse if(ch == 'x')
X    {
X    noins();
X    move(20,0);
X    addstr("You will lose any changes made this session - are you sure? (y/n)");
X    refresh();
X    ch = getch();
X    if(ch != 'y')
X	{
X	noins();
X	instruct();
X	refresh();
X    	}
X    else
X	{
X	nosave = 1;
X	addstr("\n");
X	refresh();
X	break;
X    	}
X    }
Xelse if(ch == 'm')              /* change to number of moves for the screen */
X    {
X    move(19,0);
X    addstr("How many moves for this screen? :");
X    refresh();echo();
X    gets(buffer);
X    noecho();
X    maxmoves = atoi(buffer);
X    if(maxmoves < 0 ) maxmoves = 0;
X    move(19,0);
X    addstr("                                           ");
X    if(maxmoves != 0)
X        (void) sprintf(buffer,"Moves remaining = %d   ",maxmoves);
X    else
X        (void) strcpy(buffer,"     Unlimited moves     ");
X    move(18,0);
X    addstr(buffer);
X    refresh();            /* for some reason, this seems to add a '.' to */
X			  /* the map... Ive no idea why yet... */
X    }
Xelse if(ch == 'p' || ch == 'n')       /* play the game (test) */
X    {
X	noins();
X        wscreen(num,maxmoves);
X	if(ch == 'p')
X	    {
X	    debug_disp = 0;
X	    clear();
X	    }
X	*score = 0;
X	howdead = playscreen(&num,score,bell,maxmoves,keys);
X	move(20,0);
X	if(howdead!=0)
X	    addstr(howdead);
X	else
X	    addstr("DONE!");
X	printw("; hit any key to continue\n");
X	refresh();
X	ch = (char)getchar();
X	clear();
X	rscreen(num,&maxmoves);
X	debug_disp = 1;
X	map(frow);
X	instruct();
X    }
Xelse
X    {
X    if(ch >= 'a' && ch <= 'z') ch = ch - 'a' + 'A';
X    if(ch < ' ' || ch == (char)127) ch = '.';  /* no ctrl codes, thankyou */
X    if(ch == '"') ch = (char)getchar();
X    screen[y][x] = ch;
X    move(y+1,x+1);
X    draw_map_symbol(ch);
X    nx++;
X    }
Xif(nx < 0)
X    {
X    nx = ROWLEN-1;
X    ny--;
X    }
Xif(nx >= ROWLEN)
X    {
X    nx = 0;
X    ny++;
X    }
Xif(ny < 0) ny = NOOFROWS-1;
Xif(ny >= NOOFROWS) ny = 0;
Xmove(ny+1,nx+1);
Xx=nx;
Xy=ny;
X}
X
Xif(! nosave)
X    {
X    for(y = 0; y<=NOOFROWS;y++) /* certain editors - eg ded - have a */
X                                /* habit of truncating trailing spaces*/
X            	    		/* so this should stop them! */
X        if(screen[y][ROWLEN-1] == ' ')
X	    screen[y][ROWLEN-1] = '-';
X    wscreen(num,maxmoves);
X    }
Xnoins();
Xmove(20,0);
Xrefresh();
X}
X
SHAR_EOF
echo "extracting encrypt.c"
sed 's/^X//' << \SHAR_EOF > encrypt.c
X#include "wand_head.h"
X
X/* Uses seeded random xor to encrypt because setkey doesnt work on our
X   system. 								*/
X
X/* this is the randon number seed */
X#define BLURFL 32451    /* the word blurfl is used for historical reasons */
X                        /* but it can be any nuber */
Xcrypt_file(name)
Xchar *name;
X{
Xchar buffer[1024];
Xint fd,length,loop;
X
Xif((fd = open(name,O_RDONLY)) == -1) {
X	endwin();
X	sprintf(buffer,"Wanderer: cannot open %s",name);
X	perror(buffer);
X	exit(1);
X}
Xif((length = read(fd,buffer,1024)) < 1) {
X	endwin();
X	sprintf(buffer,"Wanderer: read error on %s",name);
X	perror(buffer);
X	exit(1);
X}
Xclose(fd);
X
X/* Right, got it in here, now to encrypt the stuff */
X
Xaddstr("Running crypt routine...\n");
Xrefresh();
X
Xsrand(BLURFL);
Xfor(loop=0;loop<length;loop++)
X	buffer[loop]^=rand();
X
Xif((fd = open(name,O_WRONLY|O_TRUNC))== -1) {
X	endwin();
X	sprintf(buffer,"Wanderer: cannot write to %s",name);
X	perror(buffer);
X	exit(1);
X}
Xif(write(fd,buffer,length)!=length) {
X	endwin();
X	sprintf(buffer,"Wanderer: write error on %s",name);
X	perror(buffer);
X	exit(1);
X}
Xclose(fd);
X
X/* ok, file now contains encrypted/decrypted game. */
X/* lets go back home... */
X}
SHAR_EOF
echo "extracting fall.c"
sed 's/^X//' << \SHAR_EOF > fall.c
X#include "wand_head.h"
X
Xextern void draw_symbol();
Xextern int debug_disp;
Xextern char screen[NOOFROWS][ROWLEN+1];
X
Xint check(mx,my,x,y,dx,dy,sx,sy,howdead)
X/* check for any falling caused by something moving out of x,y along
X   vector dx,dy. All the others are constant and should really have
X   been global... 						    */
Xint x,y,sx,sy,dx,dy, *mx, *my;
Xchar howdead[25];
X{
Xint ret=0;
Xret+=fall(mx,my,x,y,sx,sy,howdead);
Xret+=fall(mx,my,x-dx,y-dy,sx,sy,howdead);
Xret+=fall(mx,my,x-dy,y-dx,sx,sy,howdead);
Xret+=fall(mx,my,x+dy,y+dx,sx,sy,howdead);
Xret+=fall(mx,my,x-dx-dy,y-dy-dx,sx,sy,howdead);
Xret+=fall(mx,my,x-dx+dy,y-dy+dx,sx,sy,howdead);
Xreturn ret;
X}
X
Xint fall(mx,my,x,y,sx,sy,howdead)  /* recursive function for falling */
X				   /* boulders and arrows */
Xint  x,y,sx,sy, *mx, *my;
Xchar howdead[25];
X{
Xint nx = x,nxu = x,nyl = y,nyr = y,retval = 0, makesound = 0;
Xif ((y>(NOOFROWS-1))||(y<0)||(x<0)||(x>(ROWLEN-1)))
X    return(0);
Xif((screen[y][x] != 'O') && (screen[y][x] != ' ') && (screen[y][x] != 'M') &&
X   (screen[y][x] !='\\') && (screen[y][x] != '/') && (screen[y][x] != '@') &&
X   (screen[y][x] != '^'))
X    return(0);
Xif(screen[y][x] == 'O')
X    {
X    if((screen[y][x-1] == ' ') && (screen[y-1][x-1] == ' '))
X        nx--;
X    else
X	{
X        if((screen[y][x+1] == ' ') && (screen[y-1][x+1] == ' '))
X            nx++;
X	else
X	    nx = -1;
X	}
X    if((screen[y][x-1] == ' ') && (screen[y+1][x-1] == ' '))
X        nxu--;
X    else
X	{
X        if((screen[y][x+1] == ' ') && (screen[y+1][x+1] == ' '))
X            nxu++;
X	else
X	    nxu = -1;
X	}
X    if((screen[y-1][x] == ' ') && (screen[y-1][x+1] == ' '))
X        nyr--;
X    else
X	{
X        if((screen[y+1][x] == ' ') && (screen[y+1][x+1] == ' '))
X            nyr++;
X	else
X	    nyr = -1;
X	}
X    if((screen[y-1][x] == ' ') && (screen[y-1][x-1] == ' '))
X        nyl--;
X    else
X	{
X        if((screen[y+1][x] == ' ') && (screen[y+1][x-1] == ' '))
X            nyl++;
X	else
X	    nyl = -1;
X	}
X    }
Xif(screen[y][x] == '\\')
X    {
X    if(screen[y-1][++nx] != ' ')
X	nx = -1;
X    if(screen[y+1][--nxu] != ' ')
X        nxu = -1;
X    if(screen[--nyr][x+1] != ' ')
X        nyr = -1;
X    if(screen[++nyl][x-1] != ' ')
X        nyl = -1;
X    }
Xif(screen[y][x] == '/')
X    {
X    if(screen[y-1][--nx] != ' ')
X	nx = -1;
X    if(screen[y+1][++nxu] != ' ')
X        nxu = -1;
X    if(screen[++nyr][x+1] != ' ')
X	nyr = -1;
X    if(screen[--nyl][x-1] != ' ')
X	nyl = -1;
X    }
Xif((screen[y][nx] != ' ') && (screen[y][nx] != 'M'))
X    nx = -1;
Xif((screen[y-1][x] == 'O') && (nx >= 0) && (y > 0) &&
X   (screen[y][nx] != '^')) /* boulder falls ? */
X    {
X    screen[y-1][x] = ' ';
X    if(screen[y][nx] == '@')
X        {
X	makesound = 1;
X    	strcpy(howdead,"a falling boulder");
X    	retval=1;
X    	}
X    if(screen[y][nx] == 'M')
X        {
X	makesound = 1;
X    	*mx = *my = -2;
X	screen[y][nx] = ' ';
X    	}
X    screen[y][nx] = 'O';
X    if(!debug_disp)
X	{
X        if((y<(sy+5)) && (y>(sy-3)) && (x>(sx-6)) && (x<(sx+6)))
X            draw_symbol((x-sx+5)*3,(y-sy+2)*2,' ');
X        if((y<(sy+4)) && (y>(sy-4)) && (nx>(sx-6)) && (nx<(sx+6)))
X            draw_symbol((nx-sx+5)*3,(y-sy+3)*2,'O');
X	}
X    else
X	{
X	move(y,x+1);
X	draw_map_symbol(' ');
X	move(y+1,nx+1);
X	draw_map_symbol('O');
X    }
X    refresh();
X
X#ifdef BOULDER_SOUND
X    {
X	int w,e,s,sw,se;
X
X	/* try to predict if boulder has stopped falling */
X	/* so we know when to trigger the sound */
X	w = screen[y][nx-1];
X	e = screen[y][nx+1];
X	s = screen[y+1][nx];
X	sw = screen[y+1][nx-1];
X	se = screen[y+1][nx+1];
X
X	if (s != ' ' && s != '/' && s != '\\' && s != 'O')
X		makesound = 1;
X	else if (s == 'O')
X	     {
X		if (w != ' ' && e != ' ')
X			makesound = 1;
X		else if (w != ' ' && e == ' ' && se != ' ')
X			makesound = 1;
X		else if (w == ' ' && e != ' ' && sw != ' ')
X			makesound = 1;
X		else if (w == ' ' && sw != ' ' && e == ' ' && se != ' ')
X			makesound = 1;
X	     }
X	else if (s == '/' && sw != ' ')
X		makesound = 1;
X	else if (s == '\\' && se != ' ')
X		makesound = 1;
X
X	if (makesound) playSound(BOULDER_SOUND);
X    }
X#endif
X
X    retval+=fall(mx,my,nx ,y+1,sx,sy,howdead);
X    retval+=check(mx,my,x,y-1,0,1,sx,sy,howdead);
X    if(screen[y+1][nx] == '@')
X        {
X	if (!makesound) playSound(BOULDER_SOUND);
X    	strcpy(howdead,"a falling boulder");
X    	return(1);
X    	}
X    if(screen[y+1][nx] == 'M')
X        {
X	if (!makesound) playSound(BOULDER_SOUND);
X    	*mx = *my = -2;
X	screen[y+1][nx] = ' ';
X    	}
X    }
Xif((screen[nyr][x] != '^')&&(screen[nyr][x] != ' ')&&(screen[nyr][x] != 'M'))
X    nyr = -1;
Xif((screen[y][x+1] == '<')&&(nyr>=0)&&(x+1<ROWLEN)) /* arrow moves ( < ) ? */
X    {
X    screen[y][x+1] = ' ';
X    if(screen[nyr][x] == '@')
X        {
X	playSound(ARROW_SOUND);
X    	strcpy(howdead,"a speeding arrow");
X    	retval = 1;
X    	}
X    if(screen[nyr][x] == 'M')
X        {
X	playSound(ARROW_SOUND);
X    	*mx = *my = -2;
X	screen[nyr][x] = ' ';
X    	}
X    screen[nyr][x] = '<';
X    if(!debug_disp)
X	{
X        if((y<(sy+4)) && (y>(sy-4)) && (x<(sx+5)) && (x>(sx-7)))
X            draw_symbol((x-sx+6)*3,(y-sy+3)*2,' ');
X        if((nyr<(sy+4)) && (nyr>(sy-4)) && (x<(sx+6)) && (x>(sx-6)))
X            draw_symbol((x-sx+5)*3,(nyr-sy+3)*2,'<');
X	}
X    else
X	{
X	move(y+1,x+2);
X	draw_map_symbol(' ');
X	move(nyr+1,x+1);
X	draw_map_symbol('<');
X	}
X    refresh();
X    retval+=fall(mx,my,x-1,nyr,sx,sy,howdead);
X    retval+=check(mx,my,x+1,y,-1,0,sx,sy,howdead);
X    if(screen[nyr][x-1] == '@')
X        {
X	playSound(ARROW_SOUND);
X    	strcpy(howdead,"a speeding arrow");
X    	return(1);
X    	}
X    if(screen[nyr][x-1] == 'M')
X        {
X	playSound(ARROW_SOUND);
X    	*mx = *my = -2;
X	screen[nyr][x-1] = ' ';
X    	}
X    }
Xif((screen[nyl][x] != ' ')&&(screen[nyl][x] != '^')&&(screen[nyl][x] != 'M'))
X    nyl = -1;
Xif((screen[y][x-1] == '>')&&(nyl>=0)&&(x>0))       /* arrow moves ( > ) ? */
X    {
X    screen[y][x-1] = ' ';
X    if(screen[nyl][x] == '@')
X        {
X	playSound(ARROW_SOUND);
X    	strcpy(howdead,"a speeding arrow");
X    	retval = 1;
X    	}
X    if(screen[nyl][x] == 'M')
X        {
X	playSound(ARROW_SOUND);
X    	*mx = *my = -2;
X	screen[nyl][x] = ' ';
X    	}
X    screen[nyl][x] = '>';
X    if(!debug_disp)
X	{
X        if((y<(sy+4)) && (y>(sy-4)) && (x<(sx+7)) && (x>(sx-5)))
X            draw_symbol((x-sx+4)*3,(y-sy+3)*2,' ');
X        if((nyl<(sy+4)) && (nyl>(sy-4)) && (x<(sx+6)) && (x>(sx-6)))
X            draw_symbol((x-sx+5)*3,(nyl-sy+3)*2,'>');
X	}
X    else
X	{
X	move(y+1,x);
X	draw_map_symbol(' ');
X	move(nyl+1,x+1);
X	draw_map_symbol('>');
X	}
X    refresh();
X    retval+=fall(mx,my,x+1,nyl,sx,sy,howdead);
X    retval+=check(mx,my,x-1,y,1,0,sx,sy,howdead);
X    if(screen[nyl][x+1] == '@')
X        {
X	playSound(ARROW_SOUND);
X    	strcpy(howdead,"a speeding arrow");
X    	return(1);
X    	}
X    if(screen[nyl][x+1] == 'M')
X        {
X	playSound(ARROW_SOUND);
X    	*mx = *my = -2;
X	screen[nyl][x+1] = ' ';
X    	}
X    }
Xif(screen[y][nxu] != ' ')
X    nxu = -1;
Xif((screen[y+1][x] == '^') && (nxu >= 0) && (y < NOOFROWS) &&
X   (screen[y][x] != '^')) /* balloon rises? */
X    {
X    screen[y+1][x] = ' ';
X    screen[y][nxu] = '^';
X    if(!debug_disp)
X	{
X        if((y<(sy+3)) && (y>(sy-5)) && (x>(sx-6)) && (x<(sx+6)))
X            draw_symbol((x-sx+5)*3,(y-sy+4)*2,' ');
X        if((y<(sy+4)) && (y>(sy-4)) && (nxu>(sx-6)) && (nxu<(sx+6)))
X            draw_symbol((nxu-sx+5)*3,(y-sy+3)*2,'^');
X	}
X    else
X	{
X	move(y+2,x+1);
X	draw_map_symbol(' ');
X	move(y+1,nxu+1);
X	draw_map_symbol('^');
X    }
X    refresh();
X    retval+=fall(mx,my,nxu ,y-1,sx,sy,howdead);
X    retval+=check(mx,my,x,y+1,0,-1,sx,sy,howdead);
X    }
Xif(retval>0)
X    return(1);
Xreturn(0);
X}
SHAR_EOF
echo "extracting game.c"
sed 's/^X//' << \SHAR_EOF > game.c
X#include "wand_head.h"
X
X#define viable(x,y) (((screen[y][x] == ' ') || (screen[y][x] == ':') ||\
X	(screen[y][x] == '@') || (screen[y][x] == '+') ||\
X	(screen[y][x] == 'S')) && (y >= 0) &&\
X	(x >= 0) && (y < NOOFROWS) && (x < ROWLEN))
X
X/* typedef struct mon_rec		*//* M002 struct mon_rec moved	*/
X/*     {				*//* to header file because it 	*/
X/*     int x,y,mx,my;			*//* is needed by save.c	*/
X/*     char under;			*/
X/*     struct mon_rec *next,*prev;	*/
X/*     };				*/
X
Xtypedef struct { int d[2]; } direction;
X
X#ifdef	LINT_ARGS	/* M001 */
Xdirection new_direction(int, int, int, int);
X#else
Xdirection new_direction();
X#endif
X
Xextern int jumpscreen();
X
Xextern int check();
X
Xextern void showpass();
X
Xextern void draw_symbol();
X
Xextern void display();
X
Xextern int fall();
X
Xextern void map();
X
Xextern void redraw_screen();
Xextern int debug_disp;
Xextern int edit_mode;
Xextern int saved_game;
Xextern char screen[NOOFROWS][ROWLEN+1];
X
X/* Add a spirit to the chain */
X/* Maintain a doubly linked list to make reuse possible.
X   tail_of_list is *NOT* the last monster allocated, but
X   the last monster alloted to a screen.  start_of_list
X   is a dummy entry to ease processing. last_of_list
X   is the last entry allocated. */
Xstatic struct mon_rec start_of_list = {0,0,0,0,0,NULL,NULL};
X
Xstruct mon_rec *tail_of_list;
Xstruct mon_rec *last_of_list;
X
Xstruct mon_rec *make_monster(x,y)
Xint x,y;
X{
Xchar *malloc();
X#define MALLOC (struct mon_rec *)malloc(sizeof(struct mon_rec))
Xstruct mon_rec *monster;
Xif(tail_of_list->next == NULL)
X    {
X    if((last_of_list = MALLOC) == NULL)
X	return NULL;
X    tail_of_list->next = last_of_list;
X    last_of_list->prev = tail_of_list;
X    last_of_list->next = NULL;
X    }
Xmonster = tail_of_list = tail_of_list->next;
Xmonster->x = x;
Xmonster->y = y;
Xmonster->mx = 1;      /* always start moving RIGHT. (fix later)  */
Xmonster->my = 0;
Xmonster->under = ' ';
Xreturn monster;
X}
X
X/* 'follow lefthand wall' algorithm for baby monsters */
X
Xdirection new_direction(x,y,bx,by)
Xint x,y,bx,by;
X{
Xdirection out;
Xif(viable((x+by),(y-bx)))
X    {
X    out.d[0] = by;
X    out.d[1] = -bx;
X    return out;
X    }
Xif(viable((x+bx),(y+by)))
X    {
X    out.d[0] = bx;
X    out.d[1] = by;
X    return out;
X    }
Xif(viable((x-by),(y+bx)))
X    {
X    out.d[0] = -by;
X    out.d[1] = bx;
X    return out;
X    }
Xif(viable((x-bx),(y-by)))
X    {
X    out.d[0] = -bx;
X    out.d[1] = -by;
X    return out;
X    }
Xout.d[0] = -bx;
Xout.d[1] = -by;
Xreturn out;
X}
X
X/* tell player if monster exists */
Xshow_monster(yes)
Xint yes;
X{
Xif(yes)           
X    draw_symbol(48,10,'M');
Xelse
X  {
X    move(48,10);
X    addstr("   ");
X    move(48,11);
X    addstr("   ");
X  }
X}
X
X/* Actual game function - Calls fall() to move
X       boulders and arrows recursively */
X/* Variable explaination :
X	All the var names make sense to ME, but some people think them a bit confusing... :-) So heres an explanation.
X   x,y : where you are
X   nx,ny : where you're trying to move to
X   sx,sy : where the screen window on the playing area is
X   mx,my : where the monster is
X   tx,ty : teleport arrival
X   bx,by : baby monster position
X   nbx,nby : where it wants to be
X   lx,ly : the place you left when teleporting
X   nf : how many diamonds youve got so far
X   new_disp : the vector the baby monster is trying
X*/
X
Xchar *playscreen(num,score,bell,maxmoves,keys)
Xint  *num, maxmoves,
X     *bell,
X     *score;
Xchar keys[10];
X{
Xint  x,y,nx,ny,deadyet =0,
X     sx = -1,sy = -1,tx = -1,ty = -1,lx = 0,ly = 0,mx = -1,my = -1,
X     bx, by, nbx, nby, tmpx,tmpy,
X     newnum,
X     max_score = 250,
X     diamonds = 0, nf = 0,hd ,vd ,xdirection,ydirection;
Xchar (*frow)[ROWLEN+1] = screen,
X     ch,
X     buffer[25];
Xstatic char     howdead[25];	/* M001 can't use auto var for return value */
Xdirection new_disp;
Xstruct mon_rec *monster,*current;
X
Xtail_of_list = &start_of_list;
X
Xfor(x=0;x<=ROWLEN;x++)
X    for(y=0;y<NOOFROWS;y++)
X	{
X	if((screen[y][x] == '*')||(screen[y][x] == '+'))
X	    {
X	    diamonds++;
X	    max_score += 10;
X	    if(screen[y][x] == '+')
X		max_score += 20;
X	    }
X        if(screen[y][x] == 'A')     /* note teleport arrival point &  */
X	    {                       /* replace with space */
X	    tx = x;
X	    ty = y;
X 	    screen[y][x] = ' ';
X	    }
X        if(screen[y][x] == '@')
X	    {
X	    sx = x;
X	    sy = y;
X	    }
X        if(screen[y][x] == 'M')     /* Put megamonster in */
X	    {
X	    mx = x;
X	    my = y;
X	    }
X	if(screen[y][x] == 'S')     /* link small monster to pointer chain */
X	    {
X	    if((monster = make_monster(x,y)) == NULL)
X		{
X		strcpy(howdead,"running out of memory");
X		return howdead;
X		}
X	    if(!viable(x,y-1))     /* make sure its running in the correct */
X		{                  /* direction..                          */
X		monster->mx = 1;
X		monster->my = 0;
X		}
X	    else if(!viable(x+1,y))
X		{
X		monster->mx = 0;
X		monster->my = 1;
X		}
X	    else if(!viable(x,y+1))
X		{
X		monster->mx = -1;
X		monster->my = 0;
X		}
X	    else if(!viable(x-1,y))
X		{
X		monster->mx = 0;
X		monster->my = -1;
X		}
X	    }
X        if(screen[y][x] == '-')
X        	screen[y][x] = ' ';
X        };
Xx=sx;
Xy=sy;
Xif((x == -1)&&(y == -1))              /* no start position in screen ? */
X    {
X    strcpy(howdead,"a screen design error");
X    return(howdead);
X    }
X
Xupdate_game:	/* M002  restored game restarts here	*/
X
Xmove(0,48);
X(void) addstr("Score\t   Diamonds");
Xmove(1,48);
X(void) addstr("\tFound\tTotal");
Xmove(3,48);
X(void) sprintf(buffer,"%d\t %d\t %d  ",*score,nf,diamonds);
X(void) addstr(buffer);
Xmove(6,48);
X(void) sprintf(buffer,"Current screen %d",*num);
X(void) addstr(buffer);
Xif(maxmoves != 0)
X(void) sprintf(buffer,"Moves remaining = %d   ",maxmoves);
Xelse
X{
X    (void) strcpy(buffer,"     Unlimited moves     ");
X    maxmoves = -1;
X};
Xmove(15,48);
X(void) addstr(buffer);
Xshow_monster(mx != -1);		/* tell player if monster exists */
X
Xif(!debug_disp)
X    display(sx,sy,frow,*score);
Xelse
X    map(frow);
X
X/* ACTUAL GAME FUNCTION - Returns method of death in string  */
X
Xwhile(deadyet == 0)
X{
X#ifdef MOUSE
X/* get next keyboard character or mouse click (AMIGA) */
Xif ((ch = mouseorkey()) == MOUSE) {
X	int mouserow, mousecol, deltax, deltay;
X#define UP	keys[0]
X#define DOWN	keys[1]
X#define LEFT	keys[2]
X#define RIGHT	keys[3]
X	/* convert mouse coordinates to the keystroke in that direction */
X	getmouse(&mouserow, &mousecol);
X	/* adjust mouse coordinates to the game window */
X	if (debug_disp) {
X		--mouserow;
X		--mousecol;
X	} else {
X    	    mouserow = mouserow/2+sy-3;
X    	    mousecol = mousecol/3+sx-5;
X	}
X	deltax = mousecol - x;
X	deltay = mouserow - y;
X	if (deltax == 0 && deltay == 0) {
X		ch = ' ';	/* no change */
X	} else if (deltax >= 0 && deltay >= 0) {
X		if (deltax > deltay) ch = RIGHT; else ch = DOWN;
X	} else if (deltax >= 0 && deltay <= 0) {
X		if (deltax > abs(deltay)) ch = RIGHT; else ch = UP;
X	} else if (deltax <= 0 && deltay >= 0) {
X		if (abs(deltax) > deltay) ch = LEFT; else ch = DOWN;
X	} else {
X		if (abs(deltax) > abs(deltay)) ch = LEFT; else ch = UP;
X	}
X}
X#else
X/* get next keyboard character */
Xch = getch();
X#endif
X
Xnx=x;
Xny=y;
X
Xif((ch == keys[3]) && (x <(ROWLEN-1)))  /* move about - but thats obvious */
X	nx++;
Xif((ch == keys[2]) && (x > 0))
X	nx--;
Xif((ch == keys[1]) && (y <(NOOFROWS-1)))
X	ny++;
Xif((ch == keys[0]) && (y > 0))
X        ny--;
X#ifndef AMIGA
Xif(ch == '1')                  /* Add or get rid of that awful sound */
X	{
X        move(10,45);
X        *bell = 1;
X        (void) addstr("Bell ON ");
X	move(16,0);
X        refresh();
X	continue;
X	}
Xif(ch == '0')
X	{
X        *bell = 0;
X        move(10,45);
X        (void) addstr("Bell OFF");
X	move(16,0);
X        refresh();
X	continue;
X	}
X#endif
Xif(ch == '~')                             /* level jump */
X	{
X	if((newnum = jumpscreen(*num)) == 0)
X	    {
X	    strcpy(howdead,"a jump error.");
X	    return howdead;
X	    }
X	if(newnum != *num)
X	    {                  /* Sorry Greg, no points for free */
X	    sprintf(howdead,"~%c",newnum);
X	    return howdead;
X	    }
X	continue;
X	}
Xif(ch == '!')                      /* look at the map */
X	{
X	if(debug_disp)
X	    continue;
X	map(frow);
X        display(sx,sy,frow,*score);
X	continue;
X	}
Xif(ch == 'q')
X        {
X        strcpy(howdead,"quitting the game");
X	return howdead;
X	}
Xif(ch == '?')
X	{
X	helpme();
X	if(debug_disp)
X	    map(frow);
X        else
X	    display(sx,sy,frow,*score);
X	continue;
X	}
Xif (ch == 'c')
X	{
X	credits();
X        redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
X	continue;
X	}
Xif((ch == '@')&&(!debug_disp))
X	{
X	sx = x;
X	sy = y;
X	display(sx,sy,frow,*score);
X	continue;
X	}
Xif(ch == '#')
X	{
X	debug_disp = 1 - debug_disp;
X	if(debug_disp)
X		map(frow);
X	else
X		{
X 		for(tmpy=0;tmpy<=(NOOFROWS+1);tmpy++)
X        		{
X        		move(tmpy,0);
X			addstr("                                          ");
X			}
X		sx = x; sy = y;
X		display(sx,sy,frow,*score);
X		}
X	continue;
X	}
Xif(ch == 'W')
X	{
X        redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
X	continue;
X	}
X
X/* M002  Added save/restore game feature.  Gregory H. Margo	*/
Xif(ch == 'S')           /* save game */
X	{
X	extern	struct	save_vars	zz;
X
X	/* stuff away important local variables to be saved */
X	/* so the game state may be acurately restored	*/
X	zz.z_x		= x;
X	zz.z_y		= y;
X	zz.z_nx		= nx;
X	zz.z_ny		= ny;
X	zz.z_sx		= sx;
X	zz.z_sy		= sy;
X	zz.z_tx		= tx;
X	zz.z_ty		= ty;
X	zz.z_lx		= lx;
X	zz.z_ly		= ly;
X	zz.z_mx		= mx;
X	zz.z_my		= my;
X	zz.z_bx		= bx;
X	zz.z_by		= by;
X	zz.z_nbx	= nbx;
X	zz.z_nby	= nby;
X	zz.z_max_score	= max_score;
X	zz.z_diamonds	= diamonds;
X	zz.z_nf		= nf;
X	zz.z_hd		= hd;
X	zz.z_vd		= vd;
X	zz.z_xdirection	= xdirection;
X	zz.z_ydirection	= ydirection;
X
X	save_game(*num, score, bell, maxmoves, &start_of_list, tail_of_list);
X	/* if save fails, we come back here */
X        redraw_screen(maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow);
X	continue;
X	}
Xif(ch == 'R')    	/* restore game */
X	{
X	extern	struct	save_vars	zz;
X
X	restore_game(num, score, bell, &maxmoves, &start_of_list, &tail_of_list);
X
X	/* recover important local variables */
X	x		= zz.z_x;
X	y		= zz.z_y;
X	nx		= zz.z_nx;
X	ny		= zz.z_ny;
X	sx		= zz.z_sx;
X	sy		= zz.z_sy;
X	tx		= zz.z_tx;
X	ty		= zz.z_ty;
X	lx		= zz.z_lx;
X	ly		= zz.z_ly;
X	mx		= zz.z_mx;
X	my		= zz.z_my;
X	bx		= zz.z_bx;
X	by		= zz.z_by;
X	nbx		= zz.z_nbx;
X	nby		= zz.z_nby;
X	max_score	= zz.z_max_score;
X	diamonds	= zz.z_diamonds;
X	nf		= zz.z_nf;
X	hd		= zz.z_hd;
X	vd		= zz.z_vd;
X	xdirection	= zz.z_xdirection;
X	ydirection	= zz.z_ydirection;
X
X	if (maxmoves == -1)
X		maxmoves = 0;	/* to get the "unlimited moves" message */
X
X	goto update_game;	/* the dreaded goto	*/
X	}
X
Xif(screen[ny][nx] == 'C')
X    {
X    playSound(CLOCK_SOUND);
X    screen[ny][nx] = ':';
X    *score+=4;
X    if(maxmoves != -1)
X        maxmoves+=250;
X    }
Xswitch(screen[ny][nx])
X    {
X    case '@': break;
X    case '*': *score+=9;
X	max_score -= 10;
X        nf++;
X	playSound(DIAMOND_SOUND);
X    case ':': *score+=1;
X        move(3,48);
X        sprintf(buffer,"%d\t %d",*score,nf);
X        (void) addstr(buffer);
X    case ' ':
X	if (screen[ny][nx] != '*') playSound(STEP_SOUND);
X	screen[y][x] = ' ';
X   	screen[ny][nx] = '@';
X	if(!debug_disp)
X	    {
X    	    draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X    	    draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
X	    }
X	else
X	    {
X	    move(y+1,x+1);
X	    draw_map_symbol(' ');
X	    move(ny+1,nx+1);
X	    draw_map_symbol('@');
X	    }
X	deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead);
X    	move(16,0);
X    	refresh();
X	y = ny;
X	x = nx;
X        break;
X    case 'O':
X	if(screen[y][nx*2-x] == 'M')
X	    {
X	    screen[y][nx*2-x] = ' ';
X	    mx = my = -1;
X	    *score+=100;
X            move(3,48);
X            sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
X            (void) addstr(buffer);
X	    playSound(DEADMONSTER_SOUND);
X	    show_monster(0);
X	    move(16,0);
X            refresh();
X	    }
X	if(screen[y][nx*2-x] == ' ')
X	    {
X	    playSound(PUSH_SOUND);
X	    screen[y][nx*2-x] = 'O';
X	    screen[y][x] = ' ';
X            screen[ny][nx] = '@';
X	    if(!debug_disp)
X		{
X                draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X                draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
X		if(nx*2-x>sx-6&&nx*2-x<sx+6)
X                    draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'O');
X		}
X	    else
X		{
X		move(y+1,x+1);
X		draw_map_symbol(' ');
X		move(ny+1,nx+1);
X		draw_map_symbol('@');
X		move(y+1,nx*2-x+1);
X		draw_map_symbol('O');
X		}
X            deadyet += fall(&mx,&my,nx*2-x,y+1,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
X            move(16,0);
X            refresh();
X	    y = ny;
X	    x = nx;
X	    }
X	break;
X    case '^':
X	if(screen[y][nx*2-x] == ' ')
X	    {
X	    screen[y][nx*2-x] = '^';
X	    screen[y][x] = ' ';
X            screen[ny][nx] = '@';
X	    if(!debug_disp)
X		{
X                draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X                draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
X		if(nx*2-x>sx-6&&nx*2-x<sx+6)
X                    draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'^');
X		}
X	    else
X		{
X		move(y+1,x+1);
X		draw_map_symbol(' ');
X		move(ny+1,nx+1);
X		draw_map_symbol('@');
X		move(y+1,nx*2-x+1);
X		draw_map_symbol('^');
X		}
X            deadyet += fall(&mx,&my,nx*2-x,y-1,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
X            deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
X            move(16,0);
X            refresh();
X	    y = ny;
X	    x = nx;
X	    }
X	break;
X    case '<':
X    case '>':
X	if(screen[ny*2-y][x] == 'M')
X	    {
X	    screen[ny*2-y][x] = ' ';
X	    mx = my = -1;
X	    *score+=100;
X            move(3,48);
X            sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
X            (void) addstr(buffer);
X	    playSound(DEADMONSTER_SOUND);
X	    show_monster(0);
X	    move(16,0);
X            refresh();
X	    }
X	if(screen[ny*2-y][x] == ' ')
X	    {
X	    screen[ny*2-y][x] = screen[ny][nx];
X	    screen[y][x] = ' ';
X            screen[ny][nx] = '@';
X	    if(!debug_disp)
X		{
X                draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X                draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
X		if(ny*2-y>sy-4&&ny*2-y<sy+4)
X                    draw_symbol((x-sx+5)*3,(ny*2-y-sy+3)*2,screen[ny*2-y][x]);
X		}
X	    else
X		{
X		move(y+1,x+1);
X		draw_map_symbol(' ');
X		move(ny+1,nx+1);
X		draw_map_symbol('@');
X		move(ny*2-y+1,x+1);
X		draw_map_symbol(screen[ny*2-y][x]);
X		}
X	        deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
X	        deadyet += fall(&mx,&my,x-1,(ny>y)?y:(y-1),sx,sy,howdead);
X	        deadyet += fall(&mx,&my,x+1,(ny>y)?y:(y-1),sx,sy,howdead);
X	        deadyet += fall(&mx,&my,x-1,ny*2-y,sx,sy,howdead);
X	        deadyet += fall(&mx,&my,x+1,ny*2-y,sx,sy,howdead);
X            move(16,0);
X            refresh();
X	    y = ny;
X	    x = nx;
X	    }
X	break;
X    case '!':
X        strcpy(howdead,"an exploding landmine");
X	deadyet = 1;
X	if(!debug_disp)
X	    {
X    	    draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X    	    draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
X	    }
X	else
X	    {
X	    move(y+1,x+1);
X	    draw_map_symbol(' ');
X	    move(ny+1,nx+1);
X	    draw_map_symbol('@');
X	    }
X        move(16,0);
X	refresh();
X	playSound(KABOOM_SOUND);
X        break;
X    case 'X':
X	if(nf == diamonds)
X	    {
X	    playSound(EXIT_SOUND);
X	    *score+=250;
X	    showpass(*num);
X	    return NULL;
X	    }
X	break;
X    case 'T':
X	if(tx > -1)
X	    {
X	    playSound(TELEPORT_SOUND);
X	    screen[ny][nx] = ' ';
X	    screen[y][x] = ' ';
X	    lx = x;
X	    ly = y;
X	    y = ty;
X	    x = tx;
X	    screen[y][x] = '@';
X	    sx = x;
X	    sy = y;
X	    *score += 20;
X            move(3,48);
X            sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
X            (void) addstr(buffer);
X	    if(!debug_disp)
X	        display(sx,sy,frow,*score);
X	    else
X		map(frow);
X	    deadyet = fall(&mx,&my,nx,ny,sx,sy,howdead);
X	    if(deadyet == 0)
X		deadyet = fall(&mx,&my,lx,ly,sx,sy,howdead);
X	    if(deadyet == 0)
X		deadyet = fall(&mx,&my,lx+1,ly-1,sx,sy,howdead);
X	    if(deadyet == 0)
X		deadyet = fall(&mx,&my,lx+1,ly+1,sx,sy,howdead);
X	    if(deadyet == 0)
X		deadyet = fall(&mx,&my,lx-1,ly+1,sx,sy,howdead);
X	    if(deadyet == 0)
X		deadyet = fall(&mx,&my,lx-1,ly-1,sx,sy,howdead);
X	    move(16,0);
X	    refresh();
X	    }
X	else
X	    {
X	    screen[ny][nx] = ' ';
X	    move(16,0);
X	    addstr("Teleport out of order");
X	    refresh();
X	    }
X	break;
X    case 'M':
X	playSound(MUNCH_SOUND);
X	strcpy(howdead,"a hungry monster");
X	deadyet = 1;
X	if(!debug_disp)
X    	    draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X	else
X	    {
X	    move(y+1,x+1);
X	    draw_map_symbol(' ');
X	    }
X        move(16,0);
X	refresh();
X        break;
X    case 'S':
X	playSound(MUNCH_SOUND);
X	strcpy(howdead,"walking into a monster");
X	deadyet = 1;
X	if(!debug_disp)
X    	    draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
X	else
X	    {
X	    move(y+1,x+1);
X	    draw_map_symbol(' ');
X	    }
X        move(16,0);
X	refresh();
X        break;
X    default:
X        break;
X    }
Xif((y == ny) && (x == nx) && (maxmoves>0))
X    {
X    (void) sprintf(buffer,"Moves remaining = %d ",--maxmoves);
X    move(15,48);
X    (void) addstr(buffer);
X    }
Xif(maxmoves == 0)
X    {
X    strcpy(howdead,"running out of time");
X    return(howdead);
X    }
Xif(!debug_disp)
X    {
X    if ((x<(sx-3))&& (deadyet ==0))         /* screen scrolling if necessary */
X        {
X        sx-=6;
X        if(sx < 4)
X	    sx = 4;
X        scroll(sx,sy,frow,*score);
X        }
X    if ((y<(sy-2))&& (deadyet == 0))
X        {
X        sy-=5;
X        if(sy < 2)
X	    sy = 2;
X        scroll(sx,sy,frow,*score);
X        }
X    if ((x>(sx+3)) && (deadyet == 0))
X        {
X        sx+=6;
X        if(sx>(ROWLEN -5))
X	    sx = ROWLEN -5;
X        scroll(sx,sy,frow,*score);
X        }
X    if ((y>(sy+2))&& (deadyet ==0))
X        {
X        sy+=5;
X        if(sy > (NOOFROWS-3))
X	    sy = NOOFROWS -3;
X        scroll(sx,sy,frow,*score);
X        }
X    }
X
X	/* MONSTER SECTION  */
X
X/* big monster first */
Xif(mx == -2)                              /* has the monster been killed ? */
X    {
X    playSound(DEADMONSTER_SOUND);
X    *score+=100;
X    mx = my = -1;
X    move(3,48);
X    sprintf(buffer,"%d\t %d\t",*score,nf);
X    (void) addstr(buffer);
X    show_monster(0);
X    move(16,0);
X    refresh();
X    }                                     /* if monster still alive */
Xif(mx != -1)                              /* then move that monster ! */
X    {
X    screen[my][mx] = ' ';
X    if(mx>x)
X        xdirection = -1;
X    else
X        xdirection = 1;
X    if(!debug_disp)
X	{
X        if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
X            draw_symbol((mx-sx+5)*3,(my-sy+3)*2,' ');
X	}
X    else
X	{
X	move(my+1,mx+1);
X	draw_map_symbol(' ');
X	}
X    if((hd = (mx-x))<0)
X	hd = -hd;
X    if((vd = (my-y))<0)
X	vd = -vd;
X    if((hd>vd)&&((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@')))
X	mx+=xdirection;
X    else
X        {
X        if(my>y)
X            ydirection = -1;
X	else
X    	    ydirection = 1;
X        if((screen[my+ydirection][mx] == ' ')||(screen[my+ydirection][mx] == '@'))
X	    my+=ydirection;
X	else
X            if((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@'))
X	mx+=xdirection;
X	}
X    if(!debug_disp)
X	{
X        if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
X            draw_symbol((mx-sx+5)*3,(my-sy+3)*2,'M');
X	}
X    else
X	{
X	move(my+1,mx+1);
X	draw_map_symbol('M');
X	}
X    if(screen[my][mx] == '@')                     /* ha! gottim! */
X	{
X	playSound(MUNCH_SOUND);
X	strcpy(howdead,"a hungry monster");
X        move(16,0);
X	refresh();
X        return(howdead);
X	}
X    screen[my][mx] = 'M';
X    move(16,0);
X    refresh();
X    }
X
Xcurrent = &start_of_list;                         /* baby monsters now */
Xwhile((current != tail_of_list)&&(!deadyet))
X    /* deal with those little monsters */
X    {
X    monster = current->next;
X    new_disp = new_direction( monster->x, monster->y, monster->mx, monster->my );
X    if(monster->under!='S')             /* if on top of another baby */
X	{
X        screen[monster->y][monster->x] = monster->under;
X        if(!debug_disp)
X	    {
X            if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
X                draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,monster->under);
X	    }
X        else
X	    {
X	        move(monster->y+1,monster->x+1);
X	        draw_map_symbol(monster->under);
X	    }
X        if(monster->under == ' ')
X	     deadyet+=check(&mx,&my,monster->x,monster->y,new_disp.d[0],new_disp.d[1],sx,sy,howdead);
X	}
X    else
X	monster->under=' ';
X    monster->mx = new_disp.d[0];
X    monster->my = new_disp.d[1];
X    monster->x += monster->mx;
X    monster->y += monster->my;
X    monster->under = screen[monster->y][monster->x];
X    screen[monster->y][monster->x] = 'S';        /* move into new space */
X    if(!debug_disp)
X	{
X        if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
X            draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'S');
X	}
X    else
X	{
X	move(monster->y+1,monster->x+1);
X	draw_map_symbol('S');
X	}
X    if(monster->under == '@')                     /* monster hit you? */
X        {
X	playSound(MUNCH_SOUND);
X	strcpy(howdead,"the little monsters");
X	move(16,0);
X	refresh();
X        return(howdead);
X        }
X    if(monster->under == '+')                    /* monster hit cage? */
X        {
X	playSound(CAGE_SOUND);
X	*score +=20;
X	max_score -= 20;
X        move(3,48);
X        sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
X        (void) addstr(buffer);
X        /* remove from chain, and insert at the end (at last_of_list) */
X	if(monster == tail_of_list)
X	    tail_of_list = tail_of_list->prev;
X	else
X	    {
X  	    current->next = monster-> next;
X	    current->next->prev = current;
X	    monster->next = NULL;
X	    monster->prev = last_of_list;
X	    last_of_list->next = monster;
X	    last_of_list = monster;
X	    }
X	screen[monster->y][monster->x] = '*';
X	if(!debug_disp)
X	    {
X            if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
X                    draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'*');
X	    }
X	else
X	    {
X	    move(monster->y+1,monster->x+1);
X	    draw_map_symbol('*');
X	    }
X        }
X    else
X	current = monster;
X    move(16,0);
X    refresh();
X    }
X
Xif((edit_mode)&&(deadyet)) {         /* stop death if testing */
X    if(!debug_disp)
X	move(18,0);
X    else
X	move(20,0);
X    addstr("You were killed by ");
X    addstr(howdead);
X    addstr("\nPress 'c' to continue.");
X    refresh();
X    ch=getch();
X    if(ch == 'c')
X	deadyet = 0;
X    if(!debug_disp)
X	move(18,0);
X     else
X	move(20,0);
X    addstr("                                                              ");
X    addstr("\n                      ");
X    refresh();
X    }
X
X}
Xreturn(howdead);
X}
SHAR_EOF
echo "End of archive 2 (of 3)"
# if you want to concatenate archives, remove anything after this line
exit