#include "wand_head.h" extern int move_monsters(); extern int jumpscreen(); extern int check(); extern void showpass(); extern void draw_symbol(); extern void display(); extern int fall(); extern void map(); extern void redraw_screen(); extern struct mon_rec *make_monster(); extern long dictsize; extern int debug_disp; extern int edit_mode; extern int record_file; extern char screen[NOOFROWS][ROWLEN+1]; extern char *edit_memory; extern char *memory_end; struct mon_rec start_of_list = {0,0,0,0,0,NULL,NULL}; struct mon_rec *last_of_list, *tail_of_list; /* Actual game function - Calls fall() to move boulders and arrows recursively. Variable explaination : All the var names make sense to ME, but some people think them a bit confusing... :-) So heres an explanation. x,y : where you are nx,ny : where you're trying to move to sx,sy : where the screen window on the playing area is mx,my : where the monster is tx,ty : teleport arrival bx,by : baby monster position nbx,nby : where it wants to be lx,ly : the place you left when teleporting nf : how many diamonds you've got so far new_disp : the vector the baby monster is trying */ char *playscreen(num, score, bell, maxmoves, keys) int *num, maxmoves, *bell; long *score; char keys[10]; { int x, y, nx, ny, deadyet = 0, sx = -1, sy = -1, tx = -1, ty = -1, lx = 0, ly = 0, mx = -1, my = -1, newnum, recording = 0, diamonds = 0, nf = 0, tmpx, tmpy; char (*frow)[ROWLEN+1] = screen, ch, *memory_ptr, buffer[25]; struct mon_rec *monster; static char howdead[25]; /* M001 can't use auto var for return value */ tail_of_list = &start_of_list; memory_ptr = edit_memory; for (x = 0; x <= ROWLEN; x++) for (y = 0; y < NOOFROWS; y++) { if ((screen[y][x] == '*') || (screen[y][x] == '+')) diamonds++; if (screen[y][x] == 'A') { /* note teleport arrival point & */ /* replace with space */ tx = x; ty = y; screen[y][x] = ' '; } if (screen[y][x] == '@') { sx = x; sy = y; } if (screen[y][x] == 'M') { /* Put megamonster in */ mx = x; my = y; } if (screen[y][x] == 'S') { /* link small monster to pointer chain */ if ((monster = make_monster(x,y)) == NULL) { strcpy(howdead,"running out of memory"); return howdead; } if (!viable(x,y-1)) { /* make sure its running in the */ /* correct direction.. */ monster->mx = 1; monster->my = 0; } else if (!viable(x+1,y)) { monster->mx = 0; monster->my = 1; } else if (!viable(x,y+1)) { monster->mx = -1; monster->my = 0; } else if (!viable(x-1,y)) { monster->mx = 0; monster->my = -1; } } if (screen[y][x] == '-') screen[y][x] = ' '; } x = sx; y = sy; if ((x == -1) && (y == -1)) { /* no start position in screen ? */ strcpy(howdead,"a screen design error"); return(howdead); } if (maxmoves < 1) maxmoves = -1; update_game: /* M002 restored game restarts here */ redraw_screen(bell,maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow); /* ACTUAL GAME FUNCTION - Returns method of death in string */ while (deadyet == 0) { switch (recording) { case 1: ch = getch(); *memory_ptr++ = ch; memory_end++; break; case 2: ch = *memory_ptr++; if (ch == '\0') ch = ')'; break; default: ch = getch(); } if ((record_file != -1) && (ch != 'q')) write(record_file,&ch,1); nx = x; ny = y; if ((ch == keys[3]) && (x <(ROWLEN-1))) /* move about - but thats obvious */ nx++; if ((ch == keys[2]) && (x > 0)) nx--; if ((ch == keys[1]) && (y <(NOOFROWS-1))) ny++; if ((ch == keys[0]) && (y > 0)) ny--; if (ch == '1') { /* Add or get rid of that awful sound */ move(17,56); *bell = 1; (void) addstr("Bell ON "); move(16,0); refresh(); continue; } if (ch == '0') { *bell = 0; move(17,56); (void) addstr("Bell OFF"); move(16,0); refresh(); continue; } if (ch == '~') { /* level jump */ if (edit_mode) continue; if ((newnum = jumpscreen(*num)) == 0) { strcpy(howdead,"a jump error."); return howdead; } if (newnum != *num) { /* Sorry Greg, no points for free */ sprintf(howdead,"~%c",newnum); return howdead; } continue; } if (ch == '!') { /* look at the map */ if (debug_disp) continue; map(frow); display(sx,sy,frow); continue; } if (ch == 'q') { strcpy(howdead,"quitting the game"); return howdead; } if (ch == '?') { helpme(1); if (debug_disp) map(frow); else display(sx,sy,frow); continue; } if ((ch == '@') && (!debug_disp)) { sx = x; sy = y; display(sx,sy,frow); continue; } if (ch == '#') { debug_disp = 1 - debug_disp; if (debug_disp) map(frow); else { for (tmpy = 0;tmpy <= (NOOFROWS+1); tmpy++) { move(tmpy,0); for (tmpx = 0;tmpx <= (ROWLEN+2); tmpx++) addch(' '); } sx = x; sy = y; display(sx,sy,frow); } continue; } if ((ch == 'W') || ((int)ch == 12)) { redraw_screen(bell,maxmoves,*num,*score,nf,diamonds,mx,sx,sy,frow); continue; } /* Edit screen memory functions */ if (edit_memory) { if ((ch == '(') && (recording == 0)) { /* start recording from beginning */ memory_end = memory_ptr = edit_memory; move(10,53); addstr(" -Recording-"); refresh(); recording = 1; continue; } if ((ch == ')') && ( recording != 0)) { /* stop recording or playback */ recording = 0; move(10,53); addstr(" -- End -- "); refresh(); move(10,53); addstr(" -Occupied- "); continue; } if ((ch == '*') && (recording == 0)) { /* playback memory */ memory_ptr = edit_memory; recording = 2; move(10,53); addstr(" -Playback- "); refresh(); continue; } if ((ch == '&') && (recording == 0)) { /* extend recording, either */ /* from end or from checkpoint */ recording = 1; move(10,53); addstr(" -Recording-"); refresh(); if (*(memory_ptr -1) != '-') memory_ptr--; continue; } if ((ch == '+') && (recording == 0) && (memory_ptr < memory_end)) { /* continue from checkpoint */ recording = 2; move(10,53); addstr(" -Playback- "); refresh(); continue; } if ((ch == '-') && (recording != 0)) { /* create or react to a checkpoint */ /* checkpoint */ move(10,53); addstr("-Checkpoint-"); refresh(); move(10,53); if (recording == 2) { recording = 0; addstr(" -Occupied- "); } else addstr(" -Recording-"); continue; } } /* end of memory functions */ /* M002 Added save/restore game feature. Gregory H. Margo */ if (ch == 'S') { /* save game */ extern struct save_vars zz; /* stuff away important local variables to be saved */ /* so the game state may be acurately restored */ zz.z_x = x; zz.z_y = y; zz.z_sx = sx; zz.z_sy = sy; zz.z_tx = tx; zz.z_ty = ty; zz.z_mx = mx; zz.z_my = my; zz.z_diamonds = diamonds; zz.z_nf = nf; save_game(*num, score, bell, maxmoves); /* NOTREACHED ... unless there's been an error. */ } if (ch == 'R') { /* restore game */ extern struct save_vars zz; restore_game(num, score, bell, &maxmoves); /* recover important local variables */ x = zz.z_x; y = zz.z_y; sx = zz.z_sx; sy = zz.z_sy; tx = zz.z_tx; ty = zz.z_ty; mx = zz.z_mx; my = zz.z_my; diamonds = zz.z_diamonds; nf = zz.z_nf; goto update_game; /* the dreaded goto */ } if (screen[ny][nx] == 'C') { screen[ny][nx] = ':'; *score+=4; if (maxmoves != -1) maxmoves+=250; } switch (screen[ny][nx]) { case '@': break; case '*': *score+=9; nf++; #ifdef NOISY if (*bell) printf("\007"); #endif case ':': *score+=1; move(3,48); sprintf(buffer,"%ld\t %d",*score,nf); (void) addstr(buffer); case ' ': screen[y][x] = ' '; screen[ny][nx] = '@'; if (!debug_disp) { draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@'); } else { move(y+1,x+1); addch(' '); move(ny+1,nx+1); addch('@'); } deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead); move(16,0); refresh(); y = ny; x = nx; break; case 'O': if ((nx == 0) || (nx == ROWLEN)) break; if (screen[y][nx*2-x] == 'M') { screen[y][nx*2-x] = ' '; mx = my = -1; *score+=100; move(3,48); sprintf(buffer,"%ld\t %d\t %d ",*score,nf,diamonds); (void) addstr(buffer); draw_symbol(50,11,' '); move(12,56); addstr(" "); move(13,56); addstr(" "); move(16,0); refresh(); } if (screen[y][nx*2-x] == ' ') { screen[y][nx*2-x] = 'O'; screen[y][x] = ' '; screen[ny][nx] = '@'; if (!debug_disp) { draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@'); if (nx*2-x>sx-6&&nx*2-x sx-6 && nx*2-x < sx+6) draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'^'); } else { move(y+1,x+1); addch(' '); move(ny+1,nx+1); addch('@'); move(y+1,nx*2-x+1); addch('^'); } deadyet += fall(&mx,&my,nx*2-x,y-1,sx,sy,howdead); deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead); deadyet += fall(&mx,&my,x,y,sx,sy,howdead); deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead); deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead); move(16,0); refresh(); y = ny; x = nx; } break; case '<': case '>': if ((ny == 0) || (ny == NOOFROWS)) break; if (screen[ny*2-y][x] == 'M') { screen[ny*2-y][x] = ' '; mx = my = -1; *score+=100; move(3,48); sprintf(buffer,"%ld\t %d\t %d ",*score,nf,diamonds); (void) addstr(buffer); draw_symbol(50,11,' '); move(12,56); addstr(" "); move(13,56); addstr(" "); move(16,0); refresh(); } if (screen[ny*2-y][x] == ' ') { screen[ny*2-y][x] = screen[ny][nx]; screen[y][x] = ' '; screen[ny][nx] = '@'; if (!debug_disp) { draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@'); if (ny*2-y > sy-4 && ny*2-y < sy+4) draw_symbol((x-sx+5)*3,(ny*2-y-sy+3)*2,screen[ny*2-y][x]); } else { move(y+1,x+1); addch(' '); move(ny+1,nx+1); addch('@'); move(ny*2-y+1,x+1); addch(screen[ny*2-y][x]); } deadyet += fall(&mx,&my,x,y,sx,sy,howdead); deadyet += fall(&mx,&my,x-1,(ny>y)?y:(y-1),sx,sy,howdead); deadyet += fall(&mx,&my,x+1,(ny>y)?y:(y-1),sx,sy,howdead); deadyet += fall(&mx,&my,x-1,ny*2-y,sx,sy,howdead); deadyet += fall(&mx,&my,x+1,ny*2-y,sx,sy,howdead); move(16,0); refresh(); y = ny; x = nx; } break; case '~': if (((2*nx-x) < 0) || ((ny*2-y) > NOOFROWS) || ((ny*2-y) < 0) || ((2*nx-x) > ROWLEN)) break; if (screen[ny*2-y][nx*2 -x] == 'M') { screen[ny*2-y][nx*2-x] = ' '; mx = my = -1; *score+=100; move(3,48); sprintf(buffer,"%ld\t %d\t %d ",*score,nf,diamonds); (void) addstr(buffer); draw_symbol(50,11,' '); move(12,56); addstr(" "); move(13,56); addstr(" "); move(16,0); refresh(); } if (screen[ny*2-y][nx*2-x] == ' ') { screen[ny*2-y][nx*2-x] = '~'; screen[y][x] = ' '; screen[ny][nx] = '@'; if (!debug_disp) { draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@'); if ((ny*2-y > sy-4) && (ny*2-y < sy+4)) draw_symbol((nx*2-x-sx+5)*3,(ny*2-y-sy+3)*2,'~'); } else { move(y+1,x+1); addch(' '); move(ny+1,nx+1); addch('@'); move(ny*2-y+1,nx*2-x+1); addch('~'); } deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead); move(16,0); refresh(); y = ny; x = nx; } break; case '!': strcpy(howdead,"an exploding landmine"); deadyet = 1; if (!debug_disp) { draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'%'); } else { move(y+1,x+1); addch(' '); move(ny+1,nx+1); addch('@'); } move(16,0); refresh(); break; case 'X': if (nf == diamonds) { *score+=250; if (dictsize) /* if passwords are enabled */ showpass(*num); return NULL; } break; case 'T': if (tx > -1) { screen[ny][nx] = ' '; screen[y][x] = ' '; lx = x; ly = y; y = ty; x = tx; screen[y][x] = '@'; sx = x; sy = y; *score += 20; move(3,48); sprintf(buffer,"%ld\t %d\t %d ",*score,nf,diamonds); (void) addstr(buffer); if (!debug_disp) display(sx,sy,frow); else map(frow); deadyet += fall(&mx,&my,nx,ny,sx,sy,howdead); if (deadyet == 0) deadyet = fall(&mx,&my,lx,ly,sx,sy,howdead); if (deadyet == 0) deadyet = fall(&mx,&my,lx+1,ly-1,sx,sy,howdead); if (deadyet == 0) deadyet = fall(&mx,&my,lx+1,ly+1,sx,sy,howdead); if (deadyet == 0) deadyet = fall(&mx,&my,lx-1,ly+1,sx,sy,howdead); if (deadyet == 0) deadyet = fall(&mx,&my,lx-1,ly-1,sx,sy,howdead); move(16,0); refresh(); } else { screen[ny][nx] = ' '; printf("Teleport out of order"); } break; case 'M': strcpy(howdead,"a hungry monster"); deadyet = 1; if (!debug_disp) draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); else { move(y+1,x+1); addch(' '); } move(16,0); refresh(); break; case 'S': strcpy(howdead,"walking into a monster"); deadyet = 1; if (!debug_disp) draw_symbol((x-sx+5)*3,(y-sy+3)*2,' '); else { move(y+1,x+1); addch(' '); } move(16,0); refresh(); break; default: break; } if ((y == ny) && (x == nx) && (maxmoves > 0)) { (void) sprintf(buffer,"Moves remaining = %d ",--maxmoves); move(15,48); (void) addstr(buffer); } if (maxmoves == 0) { strcpy(howdead,"running out of time"); deadyet = 1; if (edit_mode) maxmoves = -1; } if (!debug_disp) { if ((x < (sx-3)) && (deadyet == 0)) { /* screen scrolling if necessary */ sx-=6; if (sx < 4) sx = 4; display(sx,sy,frow); } if ((y < (sy-2)) && (deadyet == 0)) { sy-=5; if (sy < 2) sy = 2; display(sx,sy,frow); } if ((x > (sx+3)) && (!deadyet)) { sx+=6; if (sx > (ROWLEN -5)) sx = ROWLEN -5; display(sx,sy,frow); } if ((y > (sy+2)) && (!deadyet)) { sy+=5; if (sy > (NOOFROWS-3)) sy = NOOFROWS -3; display(sx,sy,frow); } } deadyet += move_monsters(&mx,&my,score,howdead,sx,sy,nf,*bell,x,y,diamonds); if ((edit_mode) && (deadyet)) { /* stop death if testing */ recording = 0; move(10,53); addstr("-Occupied- "); if (!debug_disp) move(18,0); else move(20,0); addstr("You were killed by "); addstr(howdead); addstr("\nPress 'c' to continue."); refresh(); ch = getch(); if (ch == 'c') deadyet = 0; if (!debug_disp) move(18,0); else move(20,0); addstr(" "); addstr("\n "); refresh(); } } return(howdead); }