games@tekred.TEK.COM (10/18/88)
Submitted by: Steven Shipway <csupt@cu.warwick.ac.uk> Comp.sources.games: Volume 5, Issue 73 Archive-name: wanderer2/Part01 [This is the latest version of wanderer, the original of which was posted in vol5, issues 2 & 3. See the note below from the author for what's changed. -br] [[ Here it is, the long awaited sequel - WANDERER Version 2, with builtin MSDOS port! This can be compiled on most UNIX systems, and also (thanks to Greg Margo) on PC's. It is much better than the original Wanderer, and has a builtin editor as well as having the develop and edithiscore programs built into it. There are also several new screens, a credits file, a disable passwords option, a large playing area, a save/restore game facility, .... -Steven Shipway csupt@uk.ac.warwick.cu (from outside the UK: csupt@cu.warwick.ac.uk) ...!uunet!mcvax!ukc!warwick!{maujp,csupt} ]] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 2)." # Contents: README MANIFEST edit.c fall.c game.c jump.c read.c # scores.c screens screens/no_pws wand_head.h # Wrapped by billr@saab on Mon Oct 17 11:23:30 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(4011 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X * W A N D E R E R * X ---------------------------------- X X This program requires the header files string.h and curses.h, and Xthe curses and termcap libraries libcurses.a and libtermcap.a. If your Xsystem doesnt have them then you might as well give up now. X X Still here? Good - then everythings OK. X X First thing to do is edit the wand_head.h file. Most of the filenames Xare self-explanatory - the lock file is usually in /tmp , you probably Xdont need to change it. SCREENPATH is the directory in which the screen Xfiles, screen.* , are kept. HISCOREPATH is the name of the hiscore table Xfile - this will be created when you run the program, but must have group Xand other read and write permission. Also, the directory SCREENPATH is used Xto hold the credits file. X The masterpassword is the password that you can give when you try to Xjump screen with ~ (see file wand.info) that will allow you to go to any Xscreen at will. This is for wanderer 'wizards' only. Separate passwords Xfor each screen are drawn from the file /usr/dict/words - if you dont have Xit on your system then you'll have to change the file jump.c . These passwords Xare given to the player upon completing each screen. The passwords can be Xdisabled by creating a file in the SCREENPATH directory called no_pws . X X New screens can be created by using the editor (thanx play@nl.cwi) that Xis built into the game. You enter it with the -e flag, and the screen you edit Xis held in the file ./screen . To add this one to the others, place it in the XSCREENPATH directory with a name of the form screen.* , making sure that it is Xreadable by everyone and that the screens number is subsequent to the last of Xthe screens already held in the directory. Screens may be tested with Xeither 'p' or 'n', and by using 'm' the number of moves for the screen may be Xaltered. X X The hiscore table holds only one entry per username - this is to Xprevent one or two people from taking over the entire table. If you object to Xthis feature, it is easily removed from the scores.c file. The table can also Xbe edited by the 'wizard' using the -m flag. This prompts for the Xmasterpassword before allowing you to remove any entry by typing its Xnumber. Use '0' to exit the editor. X X Not much more to say, really. Info on playing the game can be found in Xthe wand.info file. Once you have edited the header file, just type 'make' Xto run the makefile. You may need to edit the makefile so that it conforms Xwith your system. If you dont know how to do this, there's bound to be Xsomeone around who does. X X Environment variables: X Wanderer uses several of these. Here they are... XSAVEFILE ---- the path of the file to be used for saved games XNEWKEYS ---- if you want to redefine the keys XNEWNAME, NAME, USER ---- scanned in that order to get a name for the hiscore X table. X X The MSDOS port and save routines are courtesy of Greg Margo, who has also Xtidied up a lot of my messy programming :-). Any problems with them, send Xto HIM, since I wont know what to do. X X All that remains is for me to say that the source was written by me, XSteven Shipway, on a sun/3-160 called poppy at Warwick University. The Xlatter are completely unaware of this major breakthrough in software Xdesign (:-), and this is probably a good idea, since they may well disapprove Xof this use of computing time and facilities! (Only kidding) X X -Steven Shipway X X------------------------------------------------------------------------------ XSummary of flags: X X-c Reads credits file from SCREENPATH/credits X-s Shows hiscore table from HISCOREPATH X-e Enters screen editor working on file ./screen X-m Enters hiscore table editor after prompting for the MASTERPASSWORD X-f Starts game with map-type screen instead of normal screen - although I X personally think this makes the game too easy... X------------------------------------------------------------------------------ END_OF_FILE if test 4011 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(1385 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X Makefile 2 X Makefile.msdos 2 X README 1 X display.c 2 X edit.c 1 X fall.c 1 X game.c 1 X help.c 2 X icon.c 2 X jump.c 1 X m.c 2 X read.c 1 X save.c 2 X scores.c 1 X screens 1 X screens/README 2 X screens/credits 2 X screens/no_pws 1 X screens/screen.1 2 X screens/screen.10 2 X screens/screen.11 2 X screens/screen.12 2 X screens/screen.13 2 X screens/screen.14 2 X screens/screen.15 2 X screens/screen.16 2 X screens/screen.17 2 X screens/screen.18 2 X screens/screen.19 2 X screens/screen.2 2 X screens/screen.20 2 X screens/screen.3 2 X screens/screen.4 2 X screens/screen.5 2 X screens/screen.6 2 X screens/screen.7 2 X screens/screen.8 2 X screens/screen.9 2 X screens/screen.ken 2 X wand_head.h 1 END_OF_FILE if test 1385 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'edit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'edit.c'\" else echo shar: Extracting \"'edit.c'\" \(3942 characters\) sed "s/^X//" >'edit.c' <<'END_OF_FILE' X#include "wand_head.h" X Xextern char *playscreen(); X Xextern int debug_disp; Xextern char screen[NOOFROWS][ROWLEN+1]; X X/* Print instructions around the screen */ Xvoid instruct() X{ Xstatic char *inst[] = { "O Boulder", X "< > Arrows", X ": Earth", X "! Landmine", X "* Treasure", X "/ \\ Deflectors", X "+ Cage", X "= # Rock", X "T Teleport (1 max)", 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" }; Xint loop; Xfor(loop = 1;loop < 17; loop++) X { X move(loop,55); X addstr(inst[loop-1]); X } Xmove(21,0); Xaddstr("Use wanderer keys to move. q = quit, p/n = play, m = change no. of moves."); X} X Xvoid noins() X{ Xint loop; Xfor(loop =1;loop < 17; loop++) X { X move(loop,55); X addstr(" "); X } Xmove(21,0); 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; 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(); Xch = (char)getchar(); 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 move(19,0); X addstr(" "); X break; 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 scanf("%d",&maxmoves);noecho(); 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 addch(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 Xfor(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] = '-'; Xwscreen(num,maxmoves); Xmove(20,0); Xrefresh(); X} END_OF_FILE if test 3942 -ne `wc -c <'edit.c'`; then echo shar: \"'edit.c'\" unpacked with wrong size! fi # end of 'edit.c' fi if test -f 'fall.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fall.c'\" else echo shar: Extracting \"'fall.c'\" \(5261 characters\) sed "s/^X//" >'fall.c' <<'END_OF_FILE' 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,nyl = y,nyr = y,retval = 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 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-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[--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[++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)) /* boulder falls ? */ X { X screen[y-1][x] = ' '; X if(screen[y][nx] == '@') X { X strcpy(howdead,"a falling boulder"); X retval=1; X } X if(screen[y][nx] == 'M') X { 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 addch(' ');; X move(y+1,nx+1); X addch('O'); X } X refresh(); 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 strcpy(howdead,"a falling boulder"); X return(1); X } X if(screen[y+1][nx] == 'M') X { X *mx = *my = -2; X screen[y+1][nx] = ' '; X } X } Xif((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 strcpy(howdead,"a speeding arrow"); X retval = 1; X } X if(screen[nyr][x] == 'M') X { 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 addch(' '); X move(nyr+1,x+1); X addch('<'); 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 strcpy(howdead,"a speeding arrow"); X return(1); X } X if(screen[nyr][x-1] == 'M') X { X *mx = *my = -2; X screen[nyr][x-1] = ' '; X } X } Xif((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 strcpy(howdead,"a speeding arrow"); X retval = 1; X } X if(screen[nyl][x] == 'M') X { 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 addch(' '); X move(nyl+1,x+1); X addch('>'); 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 strcpy(howdead,"a speeding arrow"); X return(1); X } X if(screen[nyl][x+1] == 'M') X { X *mx = *my = -2; X screen[nyl][x+1] = ' '; X } X } Xif(retval>0) X return(1); Xreturn(0); X} END_OF_FILE if test 5261 -ne `wc -c <'fall.c'`; then echo shar: \"'fall.c'\" unpacked with wrong size! fi # end of 'fall.c' fi if test -f 'game.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'game.c'\" else echo shar: Extracting \"'game.c'\" \(19193 characters\) sed "s/^X//" >'game.c' <<'END_OF_FILE' X#include "wand_head.h" X X#define viable(x,y) (((screen[y][x] == ' ') || (screen[y][x] == ':') ||\ X (screen[y][x] == '@') || (screen[y][x] == '+')) && (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 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/* 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, 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); Xif(mx != -1) /* tell player if monster exists */ X draw_symbol(48,10,'M'); Xelse X draw_symbol(48,10,' '); 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{ Xch = getch(); X Xnx=x; Xny=y; X Xif(ch == keys[3]) /* move about - but thats obvious */ X nx++; Xif(ch == keys[2]) X nx--; Xif((ch == keys[1]) && (y<(NOOFROWS-1))) X ny++; Xif(ch == keys[0]) X ny--; 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 } 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 display(sx,sy,frow,*score); 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 /* NOTREACHED */ 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 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 case ':': *score+=1; X move(3,48); X sprintf(buffer,"%d\t %d",*score,nf); X (void) addstr(buffer); X case ' ': 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 addch(' '); X move(ny+1,nx+1); X addch('@'); 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 draw_symbol(48,10,' '); X move(16,0); X refresh(); X } X if(screen[y][nx*2-x] == ' ') X { 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 addch(' '); X move(ny+1,nx+1); X addch('@'); X move(y+1,nx*2-x+1); X addch('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 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 draw_symbol(48,10,' '); 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 addch(' '); X move(ny+1,nx+1); X addch('@'); X move(ny*2-y+1,x+1); X addch(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 addch(' '); X move(ny+1,nx+1); X addch('@'); X } X move(16,0); X refresh(); X break; X case 'X': X if(nf == diamonds) X { X *score+=250; X showpass(*num); X return NULL; X } X break; X case 'T': X if(tx > -1) X { 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 printf("Teleport out of order"); X } X break; X case 'M': 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 addch(' '); X } X move(16,0); X refresh(); X break; X case 'S': 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 addch(' '); 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 display(sx,sy,frow,*score); X } X if ((y<(sy-2))&& (deadyet == 0)) X { X sy-=5; X if(sy < 2) X sy = 2; X display(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 display(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 display(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 *score+=100; X mx = my = -1; X move(3,48); X sprintf(buffer,"%d\t %d\t",*score,nf); X (void) addstr(buffer); X draw_symbol(48,10,' '); 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 addch(' '); 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 addch('M'); X } X if(screen[my][mx] == '@') /* ha! gottim! */ X { 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; 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') 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 addch(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 addch('S'); X } X if(monster->under == '@') /* monster hit you? */ X { 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 *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 addch('*'); 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} END_OF_FILE if test 19193 -ne `wc -c <'game.c'`; then echo shar: \"'game.c'\" unpacked with wrong size! fi # end of 'game.c' fi if test -f 'jump.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'jump.c'\" else echo shar: Extracting \"'jump.c'\" \(3969 characters\) sed "s/^X//" >'jump.c' <<'END_OF_FILE' X#include "wand_head.h" X Xextern int debug_disp; Xextern int no_passwords; Xextern int maxscreens; X Xint scrn_passwd(num, passwd) /* reads password num into passwd */ Xint num; Xchar *passwd; X{ X long position; X FILE *fp; X X position = PASSWD; X while(position > 200000) X position -= 200000; X if((fp = fopen(DICTIONARY,"r")) == NULL) X return 0; X fseek(fp,position,ftell(fp)); X while(fgetc(fp) != '\n'); X fscanf(fp,"%s\n",passwd); X /* read a word into passwd */ X fclose(fp); X return (1); X} X Xvoid showpass(num) Xint num; X{ Xlong position; Xchar correct[20]; Xchar buffer[100]; XFILE *fp; Xchar ch; Xif(no_passwords) X return; Xif(!debug_disp) X move(18,0); Xelse X move(20,0); Xif(!scrn_passwd(num,correct)) X return; X(void) sprintf(buffer,"The password to jump to level %d ( using ~ ) is : %s \n",(num+1),correct); Xaddstr(buffer); Xaddstr("PRESS ANY KEY TO REMOVE IT AND CONTINUE \n"); Xrefresh(); Xch = getch(); Xif(!debug_disp) X move(18,0); Xelse X move(20,0); Xaddstr(" \n"); Xaddstr(" "); Xif(!debug_disp) X move(18,0); Xelse X move(20,0); Xrefresh(); X} X Xint jumpscreen(num) Xint num; X{ Xchar word[20], X buffer[100], X correct[20]; Xint index=0, input; Xchar ch; Xlong position; Xint fp, scrn; X Xif(no_passwords == 1) { X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr("Enter number of desired level.\n"); X refresh(); X scrn = getnum(); X if(scrn > num) { X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr(" "); X return scrn; X } X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr("No way, Jose! Back-jumping is prohibited!"); X refresh(); X return num; X } X Xif(!debug_disp) X move(16,0); Xelse X move(18,0); Xaddstr("Please enter password of screen to jump to:"); Xrefresh(); Xwhile(((word[index++] = getch()) != '\n')&&(index < 19)) X { X addch('*'); X refresh(); X } Xword[--index]='\0'; Xif(!debug_disp) X move(16,0); Xelse X move(18,0); Xaddstr("Validating... \n"); Xrefresh(); X Xif(strcmp(word,MASTERPASSWORD) == 0) X { X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr("Enter number of desired level."); X refresh(); X num = getnum(); X (void) scrn_passwd(num-1,correct); X sprintf(buffer,"Certainly master, but the correct word is %s. \n",correct); X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr(buffer); X addstr("PRESS ANY KEY TO REMOVE IT AND CONTINUE \n"); X refresh(); X getchar(); X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr(" "); X if(!debug_disp) X move(17,0); X else X move(19,0); X addstr(" "); X if(!debug_disp) X move(16,0); X else X move(18,0); X refresh(); X return num; X } X Xfor(scrn = num;scrn < maxscreens;scrn++) { X if(!scrn_passwd(scrn,correct)) X break; X if(strcmp(correct,word) == 0) X { X if(!debug_disp) X move(16,0); X else X move(18,0); X addstr("Password Validated..... Jumping to desired screen. "); X refresh(); X return ++scrn; X } X } X Xif(!debug_disp) X move(16,0); Xelse X move(18,0); X addstr("PASSWORD NOT RECOGNISED! "); Xrefresh(); Xif(!debug_disp) X move(16,0); Xelse X move(18,0); Xaddstr(" "); X Xreturn num; X} X Xint getnum() X{ Xchar ch; Xint num = 0; X for(ch = getch(),addch(ch),refresh(); ch >= '0' && ch <= '9'; ch = getch(),addch(ch),refresh()) X { X num = num * 10 + ch - '0'; X } X return num; X} END_OF_FILE if test 3969 -ne `wc -c <'jump.c'`; then echo shar: \"'jump.c'\" unpacked with wrong size! fi # end of 'jump.c' fi if test -f 'read.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'read.c'\" else echo shar: Extracting \"'read.c'\" \(1154 characters\) sed "s/^X//" >'read.c' <<'END_OF_FILE' X#include "wand_head.h" X Xextern int edit_mode; Xextern char screen[NOOFROWS][ROWLEN+1]; X Xint rscreen(num,maxmoves) Xint *maxmoves, num; X{ Xint y; XFILE *fp; Xchar name[50]; Xchar (*row_ptr)[ROWLEN+1] = screen; Xif(!edit_mode) X sprintf(name,"%s/screen.%d",SCREENPATH,num); Xelse X sprintf(name,"./screen"); Xfp = fopen(name,"r"); Xif(fp == NULL) X printf("\nFile for screen %d unavailable.\n\n",num) ; Xelse X { X for(y = 0;y<NOOFROWS;y++) X { X fgets((*row_ptr++),ROWLEN + 1,fp); X fgetc(fp); /* remove newline char*/ X }; X if(fscanf(fp,"%*s\n%d",maxmoves) != 1) X *maxmoves=0; X fclose(fp); X }; Xreturn (fp == NULL); X} X Xint wscreen(num,maxmoves) Xint maxmoves, num; X{ Xint y,x; XFILE *fp; Xchar (*row_ptr)[ROWLEN+1] = screen; Xfp = fopen("./screen","w"); Xif(fp == NULL) X printf("\nFile for screen cannot be written.\n\n") ; Xelse X { X for(y = 0;y<NOOFROWS;y++) X { X for(x = 0;x<ROWLEN;x++) X fputc(row_ptr[y][x],fp); X fputc('\n',fp); X }; X for(x = 0; x<ROWLEN;x++) X fputc('#',fp); X fputc('\n',fp); X if(maxmoves != 0) X fprintf(fp,"%d\n",maxmoves); X fclose(fp); X }; Xreturn (fp == NULL); X} END_OF_FILE if test 1154 -ne `wc -c <'read.c'`; then echo shar: \"'read.c'\" unpacked with wrong size! fi # end of 'read.c' fi if test -f 'scores.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'scores.c'\" else echo shar: Extracting \"'scores.c'\" \(5703 characters\) sed "s/^X//" >'scores.c' <<'END_OF_FILE' X#include "wand_head.h" X X#ifdef MSDOS /* M001 */ X#define LOCK X#define UNLOCK X#else X#define LOCK while((lock = creat(LOCKPATH,0)) < 0) X#define UNLOCK (void) unlink(LOCKPATH) X#endif X X#define ENTRIES 15 X X#ifndef MSDOS /* M001 */ Xextern int getuid(); X#else X#define getuid() 0 X#endif X Xextern int saved_game; /* prevent recording of hiscore if */ X /* NO_RESTORED_GAME_HISCORES is #def'd */ X Xtypedef struct X { X char howdead[25]; X char name[20]; X int score; X int level; X int uid; X } score_entry; X X#ifdef LINT_ARGS /* M001 */ Xvoid show_scores(score_entry *,int ); Xint readtable(score_entry *); X#else Xvoid show_scores(); Xint readtable(); X#endif X Xvoid show_scores(table,num) Xscore_entry *table; Xint num; X{ Xint tot = num; Xprintf("\nNo. Score Level Names How they died\n"); Xprintf("=============================================================================\n"); Xwhile(num > 0) X { X num--; X printf("%2d %5d %3d %-20s killed by %-s\n",(tot - num),table->score,table->level,table->name,table->howdead); X table++; X } Xprintf("\n\n"); X} X Xint readtable(table_ptr) Xscore_entry *table_ptr; X{ XFILE *fp; Xint numread; Xif((fp = fopen(HISCOREPATH,R_BIN)) == NULL) X { X numread = 0; X } Xelse X { X numread = fread( VOIDSTAR table_ptr, sizeof(score_entry), ENTRIES, fp); X fclose(fp); X } Xreturn numread; X} X Xint savescore(howdead,score,level,name) Xchar *howdead, *name; Xint score,level; X{ Xscore_entry table[ENTRIES + 2], X *table_ptr = table,new_entry,temp_entry; Xint numread,index = 1, numsaved, lock, already = 0, output_value = 1, X user_id; XFILE *fp; X#ifdef NO_RESTORED_GAME_HISCORES Xif(saved_game) { X printf("No hiscores recorded from restored games.\n"); X printf("\nWanderer (C) 1988 S.Shipway.\n\n"); X return 1; X} X#endif Xuser_id = getuid(); Xstrncpy(new_entry.howdead,howdead,25); Xnew_entry.howdead[24] = '\0'; /* M002 strncpy does not null terminate */ Xstrncpy(new_entry.name,name,20); Xnew_entry.name[19] = '\0'; /* M002 strncpy does not null terminate */ Xnew_entry.score = score; Xnew_entry.level = level; Xnew_entry.uid = user_id; XLOCK; Xnumread = readtable(table_ptr); Xif (numread > 0) X if(table[numread-1].score > 99999) /* stop system errors messing it up*/ X { X numread--; X printf("Erasing spurious entry in table.\n"); X } Xif(score == 0) X { X show_scores(table,numread); X UNLOCK; X return 0; X } Xif (numread > 0) X { X numread++; /* scan through until correct insertion point */ X /* pass table entries with higher scores */ X while((table_ptr->score > score)&&(index < numread)) X { X#ifdef COMPARE_BY_NAME X#define SAMEUSER(p) (strcmp((p)->name, name) == 0) X#else X#define SAMEUSER(p) ((p)->uid == user_id) X#endif X if(SAMEUSER(table_ptr)) X { X already = 1; X break; X } X table_ptr++; X index++; X } X /* pass table entries with equal score but higher or equal level */ X while((table_ptr->level>=level)&&(index<numread)&&(table_ptr->score==score)) X { X if(SAMEUSER(table_ptr)) X { X already = 1; X break; X } X table_ptr++; X index++; X } X /* if already found: done */ X if(already == 1) X { X numread--; X show_scores(table,numread); X UNLOCK; X return numread; X } X /* shift down score list */ X while(index < numread) X { X /* swap *table_ptr and new_entry */ X temp_entry = *table_ptr; X *table_ptr = new_entry; X new_entry = temp_entry; X if(SAMEUSER(&new_entry)) X { X already = 1; X numread--; /* an older entry found */ X break; X } X table_ptr++; X index++; X } X /* if all shifted without finding an older entry */ X if(already==0) X *table_ptr = new_entry; X } Xelse X { X printf("\nCreating new hiscore table.\n\n"); X *table_ptr = new_entry; X numread++; X } Xnumread = ( (numread > ENTRIES) ? ENTRIES : numread ); Xfp = fopen(HISCOREPATH,W_BIN); Xtable_ptr = table; Xnumsaved = fwrite( VOIDSTAR table_ptr, sizeof(score_entry), numread, fp); Xchmod(HISCOREPATH,0666); Xif(numsaved < numread) X { X printf("ERROR! Only %d items saved from %d !\n",numsaved,numread); X output_value = 0; X } Xfclose(fp); XUNLOCK; Xshow_scores(table,numsaved); Xreturn output_value; X} X Xvoid delete_entry(num) Xint num; X{ Xscore_entry table[ENTRIES + 22], X *table_ptr = table, X new_entry,temp_entry; Xint numread,index = 1, numsaved, lock, output_value = 1; XFILE *fp; XLOCK; Xnumread = readtable(table_ptr); Xif (numread == 0) { X printf("Missing or unreadable hiscore table.\n\n"); X UNLOCK; X exit(1); X} Xif (num > numread) { X printf("Invalid entry, choose again\n"); X UNLOCK; X return; X} Xwhile(index < num) X { X index++; X table_ptr++; X } Xwhile(index < numread) X { X index++; X *table_ptr = *(table_ptr+1); X table_ptr++; X } Xnumread--; Xfp = fopen(HISCOREPATH,W_BIN); Xtable_ptr = table; Xnumsaved = fwrite( VOIDSTAR table_ptr, sizeof(score_entry), numread, fp); Xchmod(HISCOREPATH,0666); Xif(numsaved < numread) X { X printf("ERROR! Only %d items saved from %d !\n",numsaved,numread); X output_value = 0; X } Xfclose(fp); XUNLOCK; Xshow_scores(table,numsaved); X} X Xerase_scores() X{ Xint erasenum,numread,index = 0; Xchar correct[20],c; Xscore_entry table[ENTRIES + 2], X *table_ptr = table; Xprintf("Please enter password:"); Xwhile((c = getchar()) != '\n' && index <19) { X correct[index++] = c; X } Xcorrect[index] = 0; Xif(strcmp(correct,MASTERPASSWORD)) X { X printf("\nFoo, charlatan!\n"); X return 0; X } Xnumread = readtable(table_ptr); Xshow_scores(table,numread); Xprintf("\n"); Xfor(;;) X{ Xprintf("Number to erase (0 to exit): "); Xscanf("%d",&erasenum); Xprintf("\n"); Xif(erasenum == 0) X break; Xdelete_entry(erasenum); Xprintf("\n"); X} Xprintf("Byee!\n"); X} END_OF_FILE if test 5703 -ne `wc -c <'scores.c'`; then echo shar: \"'scores.c'\" unpacked with wrong size! fi # end of 'scores.c' fi if test ! -d 'screens' ; then echo shar: Creating directory \"'screens'\" mkdir 'screens' fi if test -f 'screens/no_pws' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'screens/no_pws'\" else echo shar: Extracting \"'screens/no_pws'\" \(0 characters\) sed "s/^X//" >'screens/no_pws' <<'END_OF_FILE' END_OF_FILE if test 0 -ne `wc -c <'screens/no_pws'`; then echo shar: \"'screens/no_pws'\" unpacked with wrong size! fi # end of 'screens/no_pws' fi if test -f 'wand_head.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'wand_head.h'\" else echo shar: Extracting \"'wand_head.h'\" \(3966 characters\) sed "s/^X//" >'wand_head.h' <<'END_OF_FILE' X#include <stdio.h> X#include <curses.h> X#include <string.h> X#include <fcntl.h> X X/* I wouldnt change these if I were you - it wont give you a bigger screen */ X#define ROWLEN 40 X#define NOOFROWS 16 X X/* Change these to the necessary directories or files */ X#define SCREENPATH "/usr/games/lib/wand/screens" X#define HISCOREPATH "/usr/games/lib/wand/hiscore" X#define LOCKPATH "/tmp/wanderer.lock" /* hiscore lock file */ X#define DICTIONARY "/usr/dict/words" X X/* change this to anything, but dont forget what */ X#define MASTERPASSWORD "something else" X X/* change the numbers in this as well, but keep it in the same form */ X#define PASSWD (num * num * 4373 + num * 16927 + 39) X X/* cbreak switching via curses package. */ X/* on some Ultrix systems you may need to use crmode() and nocrmode() */ X/* if so, just change the #defs to the necessary. I also know that Xenix */ X/* systems have to use crmode, so.. */ X#ifdef XENIX X#define CBON crmode() X#define CBOFF nocrmode() X#else X#define CBON cbreak() X#define CBOFF nocbreak() X#endif X X/* To disable the recording of hiscores from games restored from saves */ X/* #define NO_RESTORED_GAME_HISCORES */ X X/* MSDOS modifications (M001) by Gregory H. Margo */ X#ifdef MSDOS X#define R_BIN "rb" /* binary mode for non-text files */ X#define W_BIN "wb" X# ifdef VOIDPTR X# define VOIDSTAR (void *) X# else X# define VOIDSTAR (char *) X# endif X#define ASKNAME /* ask user's name if not in environment */ X#define COMPARE_BY_NAME /* compare users with name, not uid */ X#undef getchar /* remove stdio's definition to use curses' */ X#define getchar() getch() /* use curse's definition instead */ X X#else /* not MSDOS */ X#define R_BIN "r" X#define W_BIN "w" X#define VOIDSTAR X#endif X X/* Save and Restore game additions (M002) by Gregory H. Margo */ X/* mon_rec structure needed by save.c */ Xstruct mon_rec X { X int x,y,mx,my; X char under; X struct mon_rec *next,*prev; X }; X X Xstruct save_vars { X int z_x, z_y, X z_nx, z_ny, X z_sx, z_sy, X z_tx, z_ty, X z_lx, z_ly, X z_mx, z_my, X z_bx, z_by, X z_nbx, z_nby, X z_max_score, X z_diamonds, X z_nf, X z_hd, X z_vd, X z_xdirection, X z_ydirection X}; X X/* prototypes added by Gregory H. Margo */ X#ifdef LINT_ARGS /* M001 */ X/* DISPLAY.c */ Xextern void map(char (*)[ROWLEN+1]); Xextern void display(int ,int ,char (*)[ROWLEN+1],int ); X X/* EDIT.C */ Xextern void instruct(void); Xextern void noins(void); Xextern void editscreen(int ,int *,int *,int ,char *); X X/* FALL.C */ Xextern int check(int *,int *,int ,int ,int ,int ,int ,int ,char *); Xextern int fall(int *,int *,int ,int ,int ,int ,char *); X X/* GAME.C */ Xextern struct mon_rec *make_monster(int ,int ); Xextern char *playscreen(int *,int *,int *,int ,char *); X X/* ICON.C */ Xextern void draw_symbol(int ,int ,char ); X X/* JUMP.C */ Xextern int scrn_passwd(int ,char *); Xextern void showpass(int ); Xextern int jumpscreen(int ); Xextern int getnum(void); X X/* READ.C */ Xextern int rscreen(int ,int *); Xextern int wscreen(int ,int ); X X/* SAVE.C */ Xextern void save_game(int ,int *,int *,int ,struct mon_rec *,struct mon_rec *); Xextern void restore_game(int *,int *,int *,int *,struct mon_rec *,struct mon_rec **); X X/* SCORES.C */ Xextern int savescore(char *,int ,int ,char *); Xextern void delete_entry(int ); Xextern int erase_scores(void); X X#else X X/* DISPLAY.c */ Xextern void map(); Xextern void display(); X X/* EDIT.C */ Xextern void instruct(); Xextern void noins(); Xextern void editscreen(); X X/* FALL.C */ Xextern int check(); Xextern int fall(); X X/* GAME.C */ Xextern struct mon_rec *make_monster(); Xextern char *playscreen(); X X/* ICON.C */ Xextern void draw_symbol(); X X/* JUMP.C */ Xextern int scrn_passwd(); Xextern void showpass(); Xextern int jumpscreen(); Xextern int getnum(); X X/* READ.C */ Xextern int rscreen(); Xextern int wscreen(); X X/* SAVE.C */ Xextern void save_game(); Xextern void restore_game(); X X/* SCORES.C */ Xextern int savescore(); Xextern void delete_entry(); Xextern int erase_scores(); X X#endif END_OF_FILE if test 3966 -ne `wc -c <'wand_head.h'`; then echo shar: \"'wand_head.h'\" unpacked with wrong size! fi # end of 'wand_head.h' fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0