1*34600Sbostic /* 2*34600Sbostic * Phantasia 3.3.2 -- Interterminal fantasy game 3*34600Sbostic * 4*34600Sbostic * Edward A. Estes 5*34600Sbostic * AT&T, March 12, 1986 6*34600Sbostic */ 7*34600Sbostic 8*34600Sbostic /* DISCLAIMER: 9*34600Sbostic * 10*34600Sbostic * This game is distributed for free as is. It is not guaranteed to work 11*34600Sbostic * in every conceivable environment. It is not even guaranteed to work 12*34600Sbostic * in ANY environment. 13*34600Sbostic * 14*34600Sbostic * This game is distributed without notice of copyright, therefore it 15*34600Sbostic * may be used in any manner the recipient sees fit. However, the 16*34600Sbostic * author assumes no responsibility for maintaining or revising this 17*34600Sbostic * game, in its original form, or any derivitives thereof. 18*34600Sbostic * 19*34600Sbostic * The author shall not be responsible for any loss, cost, or damage, 20*34600Sbostic * including consequential damage, caused by reliance on this material. 21*34600Sbostic * 22*34600Sbostic * The author makes no warranties, express or implied, including warranties 23*34600Sbostic * of merchantability or fitness for a particular purpose or use. 24*34600Sbostic * 25*34600Sbostic * AT&T is in no way connected with this game. 26*34600Sbostic */ 27*34600Sbostic 28*34600Sbostic /* 29*34600Sbostic * The program allocates as much file space as it needs to store characters, 30*34600Sbostic * so the possibility exists for the character file to grow without bound. 31*34600Sbostic * The file is purged upon normal entry to try to avoid that problem. 32*34600Sbostic * A similar problem exists for energy voids. To alleviate the problem here, 33*34600Sbostic * the void file is cleared with every new king, and a limit is placed 34*34600Sbostic * on the size of the energy void file. 35*34600Sbostic */ 36*34600Sbostic 37*34600Sbostic /* 38*34600Sbostic * Put one line of text into the file 'motd' for announcements, etc. 39*34600Sbostic */ 40*34600Sbostic 41*34600Sbostic /* 42*34600Sbostic * If ENEMY is #defined, a list of restricted login names is checked 43*34600Sbostic * in the file 'enemy'. These names are listed, one per line, with 44*34600Sbostic * no trailing blanks. 45*34600Sbostic */ 46*34600Sbostic 47*34600Sbostic /* 48*34600Sbostic * The scoreboard file is updated when someone dies, and keeps track 49*34600Sbostic * of the highest character to date for that login. 50*34600Sbostic * Being purged from the character file does not cause the scoreboard 51*34600Sbostic * to be updated. 52*34600Sbostic */ 53*34600Sbostic 54*34600Sbostic /* 55*34600Sbostic * All source files are set up for 'vi' with shiftwidth=4, tabstop=8. 56*34600Sbostic */ 57*34600Sbostic 58*34600Sbostic /**/ 59*34600Sbostic 60*34600Sbostic /* 61*34600Sbostic * main.c Main routines for Phantasia 62*34600Sbostic */ 63*34600Sbostic 64*34600Sbostic #include "include.h" 65*34600Sbostic 66*34600Sbostic /*************************************************************************** 67*34600Sbostic / FUNCTION NAME: main() 68*34600Sbostic / 69*34600Sbostic / FUNCTION: initialize state, and call main process 70*34600Sbostic / 71*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 72*34600Sbostic / 73*34600Sbostic / ARGUMENTS: 74*34600Sbostic / int argc - argument count 75*34600Sbostic / char **argv - argument vector 76*34600Sbostic / 77*34600Sbostic / RETURN VALUE: none 78*34600Sbostic / 79*34600Sbostic / MODULES CALLED: monstlist(), checkenemy(), ok_to_play(), activelist(), 80*34600Sbostic / throneroom(), checkbattle(), readmessage(), changestats(), writerecord(), 81*34600Sbostic / tradingpost(), adjuststats(), recallplayer(), displaystats(), checktampered(), 82*34600Sbostic / fabs(), rollnewplayer(), time(), exit(), sqrt(), floor(), wmove(), 83*34600Sbostic / signal(), strcat(), purgeoldplayers(), getuid(), isatty(), wclear(), 84*34600Sbostic / strcpy(), system(), altercoordinates(), cleanup(), waddstr(), procmain(), 85*34600Sbostic / playinit(), leavegame(), localtime(), getanswer(), neatstuff(), initialstate(), 86*34600Sbostic / scorelist(), titlelist() 87*34600Sbostic / 88*34600Sbostic / GLOBAL INPUTS: *Login, Throne, Wizard, Player, *stdscr, Changed, Databuf[], 89*34600Sbostic / Fileloc, Helpfile[], Stattable[] 90*34600Sbostic / 91*34600Sbostic / GLOBAL OUTPUTS: Wizard, Player, Changed, Fileloc, Timeout, *Statptr 92*34600Sbostic / 93*34600Sbostic / DESCRIPTION: 94*34600Sbostic / Process arguments, initialize program, and loop forever processing 95*34600Sbostic / player input. 96*34600Sbostic / 97*34600Sbostic /***************************************************************************/ 98*34600Sbostic 99*34600Sbostic main(argc, argv) 100*34600Sbostic int argc; 101*34600Sbostic char **argv; 102*34600Sbostic { 103*34600Sbostic bool noheader = FALSE; /* set if don't want header */ 104*34600Sbostic bool headeronly = FALSE; /* set if only want header */ 105*34600Sbostic bool examine = FALSE; /* set if examine a character */ 106*34600Sbostic long seconds; /* for time of day */ 107*34600Sbostic double dtemp; /* for temporary calculations */ 108*34600Sbostic 109*34600Sbostic initialstate(); /* init globals */ 110*34600Sbostic 111*34600Sbostic #ifdef ENEMY 112*34600Sbostic checkenemy(); /* check if denied access */ 113*34600Sbostic #endif 114*34600Sbostic 115*34600Sbostic /* process arguments */ 116*34600Sbostic while (--argc && (*++argv)[0] == '-') 117*34600Sbostic switch ((*argv)[1]) 118*34600Sbostic { 119*34600Sbostic case 's': /* short */ 120*34600Sbostic noheader = TRUE; 121*34600Sbostic break; 122*34600Sbostic 123*34600Sbostic case 'H': /* Header */ 124*34600Sbostic headeronly = TRUE; 125*34600Sbostic break; 126*34600Sbostic 127*34600Sbostic case 'a': /* all users */ 128*34600Sbostic activelist(); 129*34600Sbostic cleanup(TRUE); 130*34600Sbostic /*NOTREACHED*/ 131*34600Sbostic 132*34600Sbostic case 'p': /* purge old players */ 133*34600Sbostic purgeoldplayers(); 134*34600Sbostic cleanup(TRUE); 135*34600Sbostic /*NOTREACHED*/ 136*34600Sbostic 137*34600Sbostic case 'S': /* set 'Wizard' */ 138*34600Sbostic Wizard = (getuid() == UID); 139*34600Sbostic break; 140*34600Sbostic 141*34600Sbostic case 'x': /* examine */ 142*34600Sbostic examine = TRUE; 143*34600Sbostic break; 144*34600Sbostic 145*34600Sbostic case 'm': /* monsters */ 146*34600Sbostic monstlist(); 147*34600Sbostic cleanup(TRUE); 148*34600Sbostic /*NOTREACHED*/ 149*34600Sbostic 150*34600Sbostic case 'b': /* scoreboard */ 151*34600Sbostic scorelist(); 152*34600Sbostic cleanup(TRUE); 153*34600Sbostic /*NOTREACHED*/ 154*34600Sbostic 155*34600Sbostic case 'h': /* help */ 156*34600Sbostic cleanup(FALSE); 157*34600Sbostic strcpy(Databuf, "cat "); 158*34600Sbostic system(strcat(Databuf, Helpfile)); 159*34600Sbostic exit(0); 160*34600Sbostic /*NOTREACHED*/ 161*34600Sbostic } 162*34600Sbostic 163*34600Sbostic if (!isatty(0)) /* don't let non-tty's play */ 164*34600Sbostic cleanup(TRUE); 165*34600Sbostic /*NOTREACHED*/ 166*34600Sbostic 167*34600Sbostic playinit(); /* set up to catch signals, init curses */ 168*34600Sbostic 169*34600Sbostic if (examine) 170*34600Sbostic { 171*34600Sbostic changestats(FALSE); 172*34600Sbostic cleanup(TRUE); 173*34600Sbostic /*NOTREACHED*/ 174*34600Sbostic } 175*34600Sbostic 176*34600Sbostic if (!noheader) 177*34600Sbostic { 178*34600Sbostic titlelist(); 179*34600Sbostic purgeoldplayers(); /* clean up old characters */ 180*34600Sbostic } 181*34600Sbostic 182*34600Sbostic if (headeronly) 183*34600Sbostic cleanup(TRUE); 184*34600Sbostic /*NOTREACHED*/ 185*34600Sbostic 186*34600Sbostic #ifdef OK_TO_PLAY 187*34600Sbostic if (!ok_to_play()) 188*34600Sbostic { 189*34600Sbostic mvaddstr(23, 27, "Sorry, you can't play now.\n"); 190*34600Sbostic cleanup(TRUE); 191*34600Sbostic /*NOTREACHED*/ 192*34600Sbostic } 193*34600Sbostic #endif 194*34600Sbostic 195*34600Sbostic do 196*34600Sbostic /* get the player structure filled */ 197*34600Sbostic { 198*34600Sbostic Fileloc = -1L; 199*34600Sbostic 200*34600Sbostic mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? "); 201*34600Sbostic 202*34600Sbostic switch (getanswer("NYQ", FALSE)) 203*34600Sbostic { 204*34600Sbostic case 'Y': 205*34600Sbostic Fileloc = recallplayer(); 206*34600Sbostic break; 207*34600Sbostic 208*34600Sbostic case 'Q': 209*34600Sbostic cleanup(TRUE); 210*34600Sbostic /*NOTREACHED*/ 211*34600Sbostic 212*34600Sbostic default: 213*34600Sbostic Fileloc = rollnewplayer(); 214*34600Sbostic break; 215*34600Sbostic } 216*34600Sbostic clear(); 217*34600Sbostic } 218*34600Sbostic while (Fileloc < 0L); 219*34600Sbostic 220*34600Sbostic if (Player.p_level > 5.0) 221*34600Sbostic /* low level players have long timeout */ 222*34600Sbostic Timeout = TRUE; 223*34600Sbostic 224*34600Sbostic /* update some important player statistics */ 225*34600Sbostic strcpy(Player.p_login, Login); 226*34600Sbostic time(&seconds); 227*34600Sbostic Player.p_lastused = localtime(&seconds)->tm_yday; 228*34600Sbostic Player.p_status = S_PLAYING; 229*34600Sbostic writerecord(&Player, Fileloc); 230*34600Sbostic 231*34600Sbostic Statptr = &Stattable[Player.p_type]; /* initialize pointer */ 232*34600Sbostic 233*34600Sbostic /* catch interrupts */ 234*34600Sbostic #ifdef BSD41 235*34600Sbostic sigset(SIGINT, interrupt); 236*34600Sbostic #endif 237*34600Sbostic #ifdef BSD42 238*34600Sbostic signal(SIGINT, interrupt); 239*34600Sbostic #endif 240*34600Sbostic #ifdef SYS3 241*34600Sbostic signal(SIGINT, interrupt); 242*34600Sbostic #endif 243*34600Sbostic #ifdef SYS5 244*34600Sbostic signal(SIGINT, interrupt); 245*34600Sbostic #endif 246*34600Sbostic 247*34600Sbostic altercoordinates(Player.p_x, Player.p_y, A_FORCED); /* set some flags */ 248*34600Sbostic 249*34600Sbostic clear(); 250*34600Sbostic 251*34600Sbostic for (;;) 252*34600Sbostic /* loop forever, processing input */ 253*34600Sbostic { 254*34600Sbostic #ifdef OK_TO_PLAY 255*34600Sbostic if (!ok_to_play()) 256*34600Sbostic { 257*34600Sbostic mvaddstr(6, 0, "Whoops! Can't play now.\n"); 258*34600Sbostic leavegame(); 259*34600Sbostic /*NOTREACHED*/ 260*34600Sbostic } 261*34600Sbostic #endif 262*34600Sbostic 263*34600Sbostic adjuststats(); /* cleanup stats */ 264*34600Sbostic 265*34600Sbostic if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING) 266*34600Sbostic /* not allowed on throne -- move */ 267*34600Sbostic { 268*34600Sbostic mvaddstr(5,0,"You're not allowed in the Lord's Chamber without a crown.\n"); 269*34600Sbostic altercoordinates(0.0, 0.0, A_NEAR); 270*34600Sbostic } 271*34600Sbostic 272*34600Sbostic checktampered(); /* check for energy voids, etc. */ 273*34600Sbostic 274*34600Sbostic if (Player.p_status != S_CLOAKED 275*34600Sbostic /* not cloaked */ 276*34600Sbostic && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y) 277*34600Sbostic /* |x| = |y| */ 278*34600Sbostic && !Throne) 279*34600Sbostic /* not on throne */ 280*34600Sbostic { 281*34600Sbostic dtemp = sqrt(dtemp / 100.0); 282*34600Sbostic if (floor(dtemp) == dtemp) 283*34600Sbostic /* |x| / 100 == n*n; at a trading post */ 284*34600Sbostic { 285*34600Sbostic tradingpost(); 286*34600Sbostic clear(); 287*34600Sbostic } 288*34600Sbostic } 289*34600Sbostic 290*34600Sbostic checkbattle(); /* check for player to player battle */ 291*34600Sbostic neatstuff(); /* gurus, medics, etc. */ 292*34600Sbostic 293*34600Sbostic if (Player.p_status == S_CLOAKED) 294*34600Sbostic /* costs 3 mana per turn to be cloaked */ 295*34600Sbostic if (Player.p_mana > 3.0) 296*34600Sbostic Player.p_mana -= 3.0; 297*34600Sbostic else 298*34600Sbostic /* ran out of mana, uncloak */ 299*34600Sbostic { 300*34600Sbostic Player.p_status = S_PLAYING; 301*34600Sbostic Changed = TRUE; 302*34600Sbostic } 303*34600Sbostic 304*34600Sbostic if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED) 305*34600Sbostic /* change status back to S_PLAYING */ 306*34600Sbostic { 307*34600Sbostic Player.p_status = S_PLAYING; 308*34600Sbostic Changed = TRUE; 309*34600Sbostic } 310*34600Sbostic 311*34600Sbostic if (Changed) 312*34600Sbostic /* update file only if important stuff has changed */ 313*34600Sbostic { 314*34600Sbostic writerecord(&Player, Fileloc); 315*34600Sbostic Changed = FALSE; 316*34600Sbostic continue; 317*34600Sbostic } 318*34600Sbostic 319*34600Sbostic readmessage(); /* read message, if any */ 320*34600Sbostic 321*34600Sbostic displaystats(); /* print statistics */ 322*34600Sbostic 323*34600Sbostic move(6, 0); 324*34600Sbostic 325*34600Sbostic if (Throne) 326*34600Sbostic /* maybe make king, print prompt, etc. */ 327*34600Sbostic throneroom(); 328*34600Sbostic 329*34600Sbostic /* print status line */ 330*34600Sbostic addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit "); 331*34600Sbostic if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK) 332*34600Sbostic addstr("6:Cloak "); 333*34600Sbostic if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT) 334*34600Sbostic addstr("7:Teleport "); 335*34600Sbostic if (Player.p_specialtype >= SC_COUNCIL || Wizard) 336*34600Sbostic addstr("8:Intervene "); 337*34600Sbostic 338*34600Sbostic procmain(); /* process input */ 339*34600Sbostic } 340*34600Sbostic } 341*34600Sbostic /**/ 342*34600Sbostic /************************************************************************ 343*34600Sbostic / 344*34600Sbostic / FUNCTION NAME: initialstate() 345*34600Sbostic / 346*34600Sbostic / FUNCTION: initialize some important global variable 347*34600Sbostic / 348*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 349*34600Sbostic / 350*34600Sbostic / ARGUMENTS: none 351*34600Sbostic / 352*34600Sbostic / RETURN VALUE: none 353*34600Sbostic / 354*34600Sbostic / MODULES CALLED: time(), fopen(), srandom(), error(), getuid(), getlogin(), 355*34600Sbostic / getpwuid() 356*34600Sbostic / 357*34600Sbostic / GLOBAL INPUTS: Peoplefile[], Voidfile[], Messfile[], Monstfile[] 358*34600Sbostic / 359*34600Sbostic / GLOBAL OUTPUTS: *Energyvoidfp, Echo, Marsh, *Login, Users, Beyond, 360*34600Sbostic / Throne, Wizard, Changed, Okcount, Timeout, Windows, *Monstfp, *Messagefp, 361*34600Sbostic / *Playersfp 362*34600Sbostic / 363*34600Sbostic / DESCRIPTION: 364*34600Sbostic / Set global flags, and open files which remain open. 365*34600Sbostic / 366*34600Sbostic /************************************************************************/ 367*34600Sbostic 368*34600Sbostic initialstate() 369*34600Sbostic { 370*34600Sbostic Beyond = FALSE; 371*34600Sbostic Marsh = FALSE; 372*34600Sbostic Throne = FALSE; 373*34600Sbostic Changed = FALSE; 374*34600Sbostic Wizard = FALSE; 375*34600Sbostic Timeout = FALSE; 376*34600Sbostic Users = 0; 377*34600Sbostic Windows = FALSE; 378*34600Sbostic Echo = TRUE; 379*34600Sbostic #ifdef OK_TO_PLAY 380*34600Sbostic Okcount = 0; 381*34600Sbostic #endif 382*34600Sbostic 383*34600Sbostic /* setup login name */ 384*34600Sbostic if ((Login = getlogin()) == NULL) 385*34600Sbostic Login = getpwuid(getuid())->pw_name; 386*34600Sbostic 387*34600Sbostic /* open some files */ 388*34600Sbostic if ((Playersfp = fopen(Peoplefile, "r+")) == NULL) 389*34600Sbostic error(Peoplefile); 390*34600Sbostic /*NOTREACHED*/ 391*34600Sbostic 392*34600Sbostic if ((Monstfp = fopen(Monstfile, "r+")) == NULL) 393*34600Sbostic error(Monstfile); 394*34600Sbostic /*NOTREACHED*/ 395*34600Sbostic 396*34600Sbostic if ((Messagefp = fopen(Messfile, "r")) == NULL) 397*34600Sbostic error(Messfile); 398*34600Sbostic /*NOTREACHED*/ 399*34600Sbostic 400*34600Sbostic if ((Energyvoidfp = fopen(Voidfile, "r+")) == NULL) 401*34600Sbostic error(Voidfile); 402*34600Sbostic /*NOTREACHED*/ 403*34600Sbostic 404*34600Sbostic srandom((unsigned) time((long *) NULL)); /* prime random numbers */ 405*34600Sbostic } 406*34600Sbostic /**/ 407*34600Sbostic /************************************************************************ 408*34600Sbostic / 409*34600Sbostic / FUNCTION NAME: rollnewplayer() 410*34600Sbostic / 411*34600Sbostic / FUNCTION: roll up a new character 412*34600Sbostic / 413*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 414*34600Sbostic / 415*34600Sbostic / ARGUMENTS: none 416*34600Sbostic / 417*34600Sbostic / RETURN VALUE: none 418*34600Sbostic / 419*34600Sbostic / MODULES CALLED: initplayer(), allocrecord(), truncstring(), fabs(), wmove(), 420*34600Sbostic / wclear(), sscanf(), strcmp(), genchar(), waddstr(), findname(), mvprintw(), 421*34600Sbostic / getanswer(), getstring() 422*34600Sbostic / 423*34600Sbostic / GLOBAL INPUTS: Other, Wizard, Player, *stdscr, Databuf[] 424*34600Sbostic / 425*34600Sbostic / GLOBAL OUTPUTS: Echo 426*34600Sbostic / 427*34600Sbostic / DESCRIPTION: 428*34600Sbostic / Prompt player, and roll up new character. 429*34600Sbostic / 430*34600Sbostic /************************************************************************/ 431*34600Sbostic 432*34600Sbostic long 433*34600Sbostic rollnewplayer() 434*34600Sbostic { 435*34600Sbostic int chartype; /* character type */ 436*34600Sbostic int ch; /* input */ 437*34600Sbostic 438*34600Sbostic initplayer(&Player); /* initialize player structure */ 439*34600Sbostic 440*34600Sbostic clear(); 441*34600Sbostic mvaddstr(4, 21, "Which type of character do you want:"); 442*34600Sbostic mvaddstr(8, 4, "1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento "); 443*34600Sbostic if (Wizard) { 444*34600Sbostic addstr("7:Super ? "); 445*34600Sbostic chartype = getanswer("1234567", FALSE); 446*34600Sbostic } 447*34600Sbostic else { 448*34600Sbostic addstr("? "); 449*34600Sbostic chartype = getanswer("123456", FALSE); 450*34600Sbostic } 451*34600Sbostic 452*34600Sbostic do 453*34600Sbostic { 454*34600Sbostic genchar(chartype); /* roll up a character */ 455*34600Sbostic 456*34600Sbostic /* print out results */ 457*34600Sbostic mvprintw(12, 14, 458*34600Sbostic "Strength : %2.0f Quickness: %2.0f Mana : %2.0f\n", 459*34600Sbostic Player.p_strength, Player.p_quickness, Player.p_mana); 460*34600Sbostic mvprintw(13, 14, 461*34600Sbostic "Energy Level: %2.0f Brains : %2.0f Magic Level: %2.0f\n", 462*34600Sbostic Player.p_energy, Player.p_brains, Player.p_magiclvl); 463*34600Sbostic 464*34600Sbostic if (Player.p_type == C_EXPER || Player.p_type == C_SUPER) 465*34600Sbostic break; 466*34600Sbostic 467*34600Sbostic mvaddstr(14, 14, "Type '1' to keep >"); 468*34600Sbostic ch = getanswer(" ", TRUE); 469*34600Sbostic } 470*34600Sbostic while (ch != '1'); 471*34600Sbostic 472*34600Sbostic if (Player.p_type == C_EXPER || Player.p_type == C_SUPER) 473*34600Sbostic /* get coordinates for experimento */ 474*34600Sbostic for (;;) 475*34600Sbostic { 476*34600Sbostic mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? "); 477*34600Sbostic getstring(Databuf, SZ_DATABUF); 478*34600Sbostic sscanf(Databuf, "%F %F", &Player.p_x, &Player.p_y); 479*34600Sbostic 480*34600Sbostic if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER) 481*34600Sbostic mvaddstr(17, 0, "Invalid coordinates. Try again.\n"); 482*34600Sbostic else 483*34600Sbostic break; 484*34600Sbostic } 485*34600Sbostic 486*34600Sbostic for (;;) 487*34600Sbostic /* name the new character */ 488*34600Sbostic { 489*34600Sbostic mvprintw(18, 0, 490*34600Sbostic "Give your character a name [up to %d characters] ? ", SZ_NAME - 1); 491*34600Sbostic getstring(Player.p_name, SZ_NAME); 492*34600Sbostic truncstring(Player.p_name); /* remove trailing blanks */ 493*34600Sbostic 494*34600Sbostic if (Player.p_name[0] == '\0') 495*34600Sbostic /* no null names */ 496*34600Sbostic mvaddstr(19, 0, "Invalid name."); 497*34600Sbostic else if (findname(Player.p_name, &Other) >= 0L) 498*34600Sbostic /* cannot have duplicate names */ 499*34600Sbostic mvaddstr(19, 0, "Name already in use."); 500*34600Sbostic else 501*34600Sbostic /* name is acceptable */ 502*34600Sbostic break; 503*34600Sbostic 504*34600Sbostic addstr(" Pick another.\n"); 505*34600Sbostic } 506*34600Sbostic 507*34600Sbostic /* get a password for character */ 508*34600Sbostic Echo = FALSE; 509*34600Sbostic 510*34600Sbostic do 511*34600Sbostic { 512*34600Sbostic mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? "); 513*34600Sbostic getstring(Player.p_password, SZ_PASSWORD); 514*34600Sbostic mvaddstr(21, 0, "One more time to verify ? "); 515*34600Sbostic getstring(Databuf, SZ_PASSWORD); 516*34600Sbostic } 517*34600Sbostic while (strcmp(Player.p_password, Databuf) != 0); 518*34600Sbostic 519*34600Sbostic Echo = TRUE; 520*34600Sbostic 521*34600Sbostic return(allocrecord()); 522*34600Sbostic } 523*34600Sbostic /**/ 524*34600Sbostic /************************************************************************ 525*34600Sbostic / 526*34600Sbostic / FUNCTION NAME: procmain() 527*34600Sbostic / 528*34600Sbostic / FUNCTION: process input from player 529*34600Sbostic / 530*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 531*34600Sbostic / 532*34600Sbostic / ARGUMENTS: none 533*34600Sbostic / 534*34600Sbostic / RETURN VALUE: none 535*34600Sbostic / 536*34600Sbostic / MODULES CALLED: dotampered(), changestats(), inputoption(), allstatslist(), 537*34600Sbostic / fopen(), wmove(), drandom(), sscanf(), fclose(), altercoordinates(), 538*34600Sbostic / waddstr(), fprintf(), distance(), userlist(), leavegame(), encounter(), 539*34600Sbostic / getstring(), wclrtobot() 540*34600Sbostic / 541*34600Sbostic / GLOBAL INPUTS: Circle, Illcmd[], Throne, Wizard, Player, *stdscr, 542*34600Sbostic / Databuf[], Illmove[], Messfile[] 543*34600Sbostic / 544*34600Sbostic / GLOBAL OUTPUTS: Player, Changed 545*34600Sbostic / 546*34600Sbostic / DESCRIPTION: 547*34600Sbostic / Process main menu options. 548*34600Sbostic / 549*34600Sbostic /************************************************************************/ 550*34600Sbostic 551*34600Sbostic procmain() 552*34600Sbostic { 553*34600Sbostic int ch; /* input */ 554*34600Sbostic double x; /* desired new x coordinate */ 555*34600Sbostic double y; /* desired new y coordinate */ 556*34600Sbostic double temp; /* for temporary calculations */ 557*34600Sbostic FILE *fp; /* for opening files */ 558*34600Sbostic register int loop; /* a loop counter */ 559*34600Sbostic bool hasmoved = FALSE; /* set if player has moved */ 560*34600Sbostic 561*34600Sbostic ch = inputoption(); 562*34600Sbostic mvaddstr(4, 0, "\n\n"); /* clear status area */ 563*34600Sbostic 564*34600Sbostic move(7, 0); 565*34600Sbostic clrtobot(); /* clear data on bottom area of screen */ 566*34600Sbostic 567*34600Sbostic if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7')) 568*34600Sbostic /* valar cannot move */ 569*34600Sbostic ch = ' '; 570*34600Sbostic 571*34600Sbostic switch (ch) 572*34600Sbostic { 573*34600Sbostic case 'K': /* move up/north */ 574*34600Sbostic case 'N': 575*34600Sbostic x = Player.p_x; 576*34600Sbostic y = Player.p_y + MAXMOVE(); 577*34600Sbostic hasmoved = TRUE; 578*34600Sbostic break; 579*34600Sbostic 580*34600Sbostic case 'J': /* move down/south */ 581*34600Sbostic case 'S': 582*34600Sbostic x = Player.p_x; 583*34600Sbostic y = Player.p_y - MAXMOVE(); 584*34600Sbostic hasmoved = TRUE; 585*34600Sbostic break; 586*34600Sbostic 587*34600Sbostic case 'L': /* move right/east */ 588*34600Sbostic case 'E': 589*34600Sbostic x = Player.p_x + MAXMOVE(); 590*34600Sbostic y = Player.p_y; 591*34600Sbostic hasmoved = TRUE; 592*34600Sbostic break; 593*34600Sbostic 594*34600Sbostic case 'H': /* move left/west */ 595*34600Sbostic case 'W': 596*34600Sbostic x = Player.p_x - MAXMOVE(); 597*34600Sbostic y = Player.p_y; 598*34600Sbostic hasmoved = TRUE; 599*34600Sbostic break; 600*34600Sbostic 601*34600Sbostic default: /* rest */ 602*34600Sbostic Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0 603*34600Sbostic + Player.p_level / 3.0 + 2.0; 604*34600Sbostic Player.p_energy = 605*34600Sbostic MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield); 606*34600Sbostic 607*34600Sbostic if (Player.p_status != S_CLOAKED) 608*34600Sbostic /* cannot find mana if cloaked */ 609*34600Sbostic { 610*34600Sbostic Player.p_mana += (Circle + Player.p_level) / 4.0; 611*34600Sbostic 612*34600Sbostic if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne) 613*34600Sbostic /* wandering monster */ 614*34600Sbostic encounter(-1); 615*34600Sbostic } 616*34600Sbostic break; 617*34600Sbostic 618*34600Sbostic case 'X': /* change/examine a character */ 619*34600Sbostic changestats(TRUE); 620*34600Sbostic break; 621*34600Sbostic 622*34600Sbostic case '1': /* move */ 623*34600Sbostic for (loop = 3; loop; --loop) 624*34600Sbostic { 625*34600Sbostic mvaddstr(4, 0, "X Y Coordinates ? "); 626*34600Sbostic getstring(Databuf, SZ_DATABUF); 627*34600Sbostic 628*34600Sbostic if (sscanf(Databuf, "%F %F", &x, &y) != 2) 629*34600Sbostic mvaddstr(5, 0, "Try again\n"); 630*34600Sbostic else if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE()) 631*34600Sbostic ILLMOVE(); 632*34600Sbostic else 633*34600Sbostic { 634*34600Sbostic hasmoved = TRUE; 635*34600Sbostic break; 636*34600Sbostic } 637*34600Sbostic } 638*34600Sbostic break; 639*34600Sbostic 640*34600Sbostic case '2': /* players */ 641*34600Sbostic userlist(TRUE); 642*34600Sbostic break; 643*34600Sbostic 644*34600Sbostic case '3': /* message */ 645*34600Sbostic mvaddstr(4, 0, "Message ? "); 646*34600Sbostic getstring(Databuf, SZ_DATABUF); 647*34600Sbostic /* we open the file for writing to erase any data which is already there */ 648*34600Sbostic fp = fopen(Messfile, "w"); 649*34600Sbostic if (Databuf[0] != '\0') 650*34600Sbostic fprintf(fp, "%s: %s", Player.p_name, Databuf); 651*34600Sbostic fclose(fp); 652*34600Sbostic break; 653*34600Sbostic 654*34600Sbostic case '4': /* stats */ 655*34600Sbostic allstatslist(); 656*34600Sbostic break; 657*34600Sbostic 658*34600Sbostic case '5': /* good-bye */ 659*34600Sbostic leavegame(); 660*34600Sbostic /*NOTREACHED*/ 661*34600Sbostic 662*34600Sbostic case '6': /* cloak */ 663*34600Sbostic if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK) 664*34600Sbostic ILLCMD(); 665*34600Sbostic else if (Player.p_status == S_CLOAKED) 666*34600Sbostic Player.p_status = S_PLAYING; 667*34600Sbostic else if (Player.p_mana < MM_CLOAK) 668*34600Sbostic mvaddstr(5, 0, "No mana left.\n"); 669*34600Sbostic else 670*34600Sbostic { 671*34600Sbostic Changed = TRUE; 672*34600Sbostic Player.p_mana -= MM_CLOAK; 673*34600Sbostic Player.p_status = S_CLOAKED; 674*34600Sbostic } 675*34600Sbostic break; 676*34600Sbostic 677*34600Sbostic case '7': /* teleport */ 678*34600Sbostic /* 679*34600Sbostic * conditions for teleport 680*34600Sbostic * - 20 per (level plus magic level) 681*34600Sbostic * - OR council of the wise or valar or ex-valar 682*34600Sbostic * - OR transport from throne 683*34600Sbostic * transports from throne cost no mana 684*34600Sbostic */ 685*34600Sbostic if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT) 686*34600Sbostic ILLCMD(); 687*34600Sbostic else 688*34600Sbostic for (loop = 3; loop; --loop) 689*34600Sbostic { 690*34600Sbostic mvaddstr(4, 0, "X Y Coordinates ? "); 691*34600Sbostic getstring(Databuf, SZ_DATABUF); 692*34600Sbostic 693*34600Sbostic if (sscanf(Databuf, "%F %F", &x, &y) == 2) 694*34600Sbostic { 695*34600Sbostic temp = distance(Player.p_x, x, Player.p_y, y); 696*34600Sbostic if (!Throne 697*34600Sbostic /* can transport anywhere from throne */ 698*34600Sbostic && Player.p_specialtype <= SC_COUNCIL 699*34600Sbostic /* council, valar can transport anywhere */ 700*34600Sbostic && temp > (Player.p_level + Player.p_magiclvl) * 20.0) 701*34600Sbostic /* can only move 20 per exp. level + mag. level */ 702*34600Sbostic ILLMOVE(); 703*34600Sbostic else 704*34600Sbostic { 705*34600Sbostic temp = (temp / 75.0 + 1.0) * 20.0; /* mana used */ 706*34600Sbostic 707*34600Sbostic if (!Throne && temp > Player.p_mana) 708*34600Sbostic mvaddstr(5, 0, "Not enough power for that distance.\n"); 709*34600Sbostic else 710*34600Sbostic { 711*34600Sbostic if (!Throne) 712*34600Sbostic Player.p_mana -= temp; 713*34600Sbostic hasmoved = TRUE; 714*34600Sbostic break; 715*34600Sbostic } 716*34600Sbostic } 717*34600Sbostic } 718*34600Sbostic } 719*34600Sbostic break; 720*34600Sbostic 721*34600Sbostic case 'C': 722*34600Sbostic case '9': /* monster */ 723*34600Sbostic if (Throne) 724*34600Sbostic /* no monsters while on throne */ 725*34600Sbostic mvaddstr(5, 0, "No monsters in the chamber!\n"); 726*34600Sbostic else if (Player.p_specialtype != SC_VALAR) 727*34600Sbostic /* the valar cannot call monsters */ 728*34600Sbostic { 729*34600Sbostic Player.p_sin += 1e-6; 730*34600Sbostic encounter(-1); 731*34600Sbostic } 732*34600Sbostic break; 733*34600Sbostic 734*34600Sbostic case '0': /* decree */ 735*34600Sbostic if (Wizard || Player.p_specialtype == SC_KING && Throne) 736*34600Sbostic /* kings must be on throne to decree */ 737*34600Sbostic dotampered(); 738*34600Sbostic else 739*34600Sbostic ILLCMD(); 740*34600Sbostic break; 741*34600Sbostic 742*34600Sbostic case '8': /* intervention */ 743*34600Sbostic if (Wizard || Player.p_specialtype >= SC_COUNCIL) 744*34600Sbostic dotampered(); 745*34600Sbostic else 746*34600Sbostic ILLCMD(); 747*34600Sbostic break; 748*34600Sbostic } 749*34600Sbostic 750*34600Sbostic if (hasmoved) 751*34600Sbostic /* player has moved -- alter coordinates, and do random monster */ 752*34600Sbostic { 753*34600Sbostic altercoordinates(x, y, A_SPECIFIC); 754*34600Sbostic 755*34600Sbostic if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne) 756*34600Sbostic encounter(-1); 757*34600Sbostic } 758*34600Sbostic } 759*34600Sbostic /**/ 760*34600Sbostic #ifdef ENEMY 761*34600Sbostic /************************************************************************ 762*34600Sbostic / 763*34600Sbostic / FUNCTION NAME: checkenemy() 764*34600Sbostic / 765*34600Sbostic / FUNCTION: check login name against enemy list 766*34600Sbostic / 767*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 768*34600Sbostic / 769*34600Sbostic / ARGUMENTS: none 770*34600Sbostic / 771*34600Sbostic / RETURN VALUE: none 772*34600Sbostic / 773*34600Sbostic / MODULES CALLED: fopen(), fgets(), strcmp(), fclose(), printf(), cleanup() 774*34600Sbostic / 775*34600Sbostic / GLOBAL INPUTS: *Login, Databuf[], Enemyfile[] 776*34600Sbostic / 777*34600Sbostic / GLOBAL OUTPUTS: none 778*34600Sbostic / 779*34600Sbostic / DESCRIPTION: 780*34600Sbostic / The enemy file has a list of login names which are denied 781*34600Sbostic / access to Phantasia. 782*34600Sbostic / We scan this list and exit if the current login name is 783*34600Sbostic / found in the list. 784*34600Sbostic / 785*34600Sbostic /************************************************************************/ 786*34600Sbostic 787*34600Sbostic checkenemy() 788*34600Sbostic { 789*34600Sbostic FILE *fp; /* to open enemy file */ 790*34600Sbostic 791*34600Sbostic /* check hit list of restricted accounts */ 792*34600Sbostic if ((fp = fopen(Enemyfile, "r")) != NULL) 793*34600Sbostic { 794*34600Sbostic while (fgets(Databuf, SZ_DATABUF, fp) != NULL) 795*34600Sbostic if (strcmp(Login, Databuf) == 0) 796*34600Sbostic { 797*34600Sbostic printf ("The Phantasia privileges for the account \"%s\" have been revoked.\n", Login); 798*34600Sbostic printf ("Mail comments to %s.\n", WIZARD); 799*34600Sbostic fclose(fp); 800*34600Sbostic cleanup(TRUE); 801*34600Sbostic /*NOTREACHED*/ 802*34600Sbostic } 803*34600Sbostic fclose (fp); 804*34600Sbostic } 805*34600Sbostic } 806*34600Sbostic #endif 807*34600Sbostic 808*34600Sbostic /**/ 809*34600Sbostic /************************************************************************ 810*34600Sbostic / 811*34600Sbostic / FUNCTION NAME: titlelist() 812*34600Sbostic / 813*34600Sbostic / FUNCTION: print title page 814*34600Sbostic / 815*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 816*34600Sbostic / 817*34600Sbostic / ARGUMENTS: none 818*34600Sbostic / 819*34600Sbostic / RETURN VALUE: none 820*34600Sbostic / 821*34600Sbostic / MODULES CALLED: fread(), fseek(), fopen(), fgets(), wmove(), strcpy(), 822*34600Sbostic / fclose(), strlen(), waddstr(), sprintf(), wrefresh() 823*34600Sbostic / 824*34600Sbostic / GLOBAL INPUTS: Lines, Other, *stdscr, Databuf[], Lastdead[], Motdfile[], 825*34600Sbostic / *Playersfp 826*34600Sbostic / 827*34600Sbostic / GLOBAL OUTPUTS: Lines 828*34600Sbostic / 829*34600Sbostic / DESCRIPTION: 830*34600Sbostic / Print important information about game, players, etc. 831*34600Sbostic / 832*34600Sbostic /************************************************************************/ 833*34600Sbostic 834*34600Sbostic titlelist() 835*34600Sbostic { 836*34600Sbostic register FILE *fp; /* used for opening various files */ 837*34600Sbostic bool councilfound = FALSE; /* set if we find a member of the council */ 838*34600Sbostic bool kingfound = FALSE; /* set if we find a king */ 839*34600Sbostic double hiexp, nxtexp; /* used for finding the two highest players */ 840*34600Sbostic double hilvl, nxtlvl; /* used for finding the two highest players */ 841*34600Sbostic char hiname[21], nxtname[21];/* used for finding the two highest players */ 842*34600Sbostic 843*34600Sbostic mvaddstr(0, 14, "W e l c o m e t o P h a n t a s i a (vers. 3.3.2)!"); 844*34600Sbostic 845*34600Sbostic /* print message of the day */ 846*34600Sbostic if ((fp = fopen(Motdfile, "r")) != NULL 847*34600Sbostic && fgets(Databuf, SZ_DATABUF, fp) != NULL) 848*34600Sbostic { 849*34600Sbostic mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf); 850*34600Sbostic fclose(fp); 851*34600Sbostic } 852*34600Sbostic 853*34600Sbostic /* search for king */ 854*34600Sbostic fseek(Playersfp, 0L, 0); 855*34600Sbostic while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 856*34600Sbostic if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) 857*34600Sbostic /* found the king */ 858*34600Sbostic { 859*34600Sbostic sprintf(Databuf, "The present ruler is %s Level:%.0f", 860*34600Sbostic Other.p_name, Other.p_level); 861*34600Sbostic mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf); 862*34600Sbostic kingfound = TRUE; 863*34600Sbostic break; 864*34600Sbostic } 865*34600Sbostic 866*34600Sbostic if (!kingfound) 867*34600Sbostic mvaddstr(4, 24, "There is no ruler at this time."); 868*34600Sbostic 869*34600Sbostic /* search for valar */ 870*34600Sbostic fseek(Playersfp, 0L, 0); 871*34600Sbostic while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 872*34600Sbostic if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED) 873*34600Sbostic /* found the valar */ 874*34600Sbostic { 875*34600Sbostic sprintf(Databuf, "The Valar is %s Login: %s", Other.p_name, Other.p_login); 876*34600Sbostic mvaddstr(6, 40 - strlen(Databuf) / 2 , Databuf); 877*34600Sbostic break; 878*34600Sbostic } 879*34600Sbostic 880*34600Sbostic /* search for council of the wise */ 881*34600Sbostic fseek(Playersfp, 0L, 0); 882*34600Sbostic Lines = 10; 883*34600Sbostic while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 884*34600Sbostic if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED) 885*34600Sbostic /* found a member of the council */ 886*34600Sbostic { 887*34600Sbostic if (!councilfound) 888*34600Sbostic { 889*34600Sbostic mvaddstr(8, 30, "Council of the Wise:"); 890*34600Sbostic councilfound = TRUE; 891*34600Sbostic } 892*34600Sbostic 893*34600Sbostic /* This assumes a finite (<=5) number of C.O.W.: */ 894*34600Sbostic sprintf(Databuf, "%s Login: %s", Other.p_name, Other.p_login); 895*34600Sbostic mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf); 896*34600Sbostic } 897*34600Sbostic 898*34600Sbostic /* search for the two highest players */ 899*34600Sbostic nxtname[0] = hiname[0] = '\0'; 900*34600Sbostic hiexp = 0.0; 901*34600Sbostic nxtlvl = hilvl = 0; 902*34600Sbostic 903*34600Sbostic fseek(Playersfp, 0L, 0); 904*34600Sbostic while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 905*34600Sbostic if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED) 906*34600Sbostic /* highest found so far */ 907*34600Sbostic { 908*34600Sbostic nxtexp = hiexp; 909*34600Sbostic hiexp = Other.p_experience; 910*34600Sbostic nxtlvl = hilvl; 911*34600Sbostic hilvl = Other.p_level; 912*34600Sbostic strcpy(nxtname, hiname); 913*34600Sbostic strcpy(hiname, Other.p_name); 914*34600Sbostic } 915*34600Sbostic else if (Other.p_experience > nxtexp 916*34600Sbostic && Other.p_specialtype <= SC_KING 917*34600Sbostic && Other.p_status != S_NOTUSED) 918*34600Sbostic /* next highest found so far */ 919*34600Sbostic { 920*34600Sbostic nxtexp = Other.p_experience; 921*34600Sbostic nxtlvl = Other.p_level; 922*34600Sbostic strcpy(nxtname, Other.p_name); 923*34600Sbostic } 924*34600Sbostic 925*34600Sbostic mvaddstr(15, 28, "Highest characters are:"); 926*34600Sbostic sprintf(Databuf, "%s Level:%.0f and %s Level:%.0f", 927*34600Sbostic hiname, hilvl, nxtname, nxtlvl); 928*34600Sbostic mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf); 929*34600Sbostic 930*34600Sbostic /* print last to die */ 931*34600Sbostic if ((fp = fopen(Lastdead,"r")) != NULL 932*34600Sbostic && fgets(Databuf, SZ_DATABUF, fp) != NULL) 933*34600Sbostic { 934*34600Sbostic mvaddstr(19, 25, "The last character to die was:"); 935*34600Sbostic mvaddstr(20, 40 - strlen(Databuf) / 2,Databuf); 936*34600Sbostic fclose(fp); 937*34600Sbostic } 938*34600Sbostic 939*34600Sbostic refresh(); 940*34600Sbostic } 941*34600Sbostic /**/ 942*34600Sbostic /************************************************************************ 943*34600Sbostic / 944*34600Sbostic / FUNCTION NAME: recallplayer() 945*34600Sbostic / 946*34600Sbostic / FUNCTION: find a character on file 947*34600Sbostic / 948*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 949*34600Sbostic / 950*34600Sbostic / ARGUMENTS: none 951*34600Sbostic / 952*34600Sbostic / RETURN VALUE: none 953*34600Sbostic / 954*34600Sbostic / MODULES CALLED: writerecord(), truncstring(), more(), death(), wmove(), 955*34600Sbostic / wclear(), strcmp(), printw(), cleanup(), waddstr(), findname(), mvprintw(), 956*34600Sbostic / getanswer(), getstring() 957*34600Sbostic / 958*34600Sbostic / GLOBAL INPUTS: Player, *stdscr, Databuf[] 959*34600Sbostic / 960*34600Sbostic / GLOBAL OUTPUTS: Echo, Player 961*34600Sbostic / 962*34600Sbostic / DESCRIPTION: 963*34600Sbostic / Search for a character of a certain name, and check password. 964*34600Sbostic / 965*34600Sbostic /************************************************************************/ 966*34600Sbostic 967*34600Sbostic long 968*34600Sbostic recallplayer() 969*34600Sbostic { 970*34600Sbostic long loc = 0L; /* location in player file */ 971*34600Sbostic register int loop; /* loop counter */ 972*34600Sbostic int ch; /* input */ 973*34600Sbostic 974*34600Sbostic clear(); 975*34600Sbostic mvprintw(10, 0, "What was your character's name ? "); 976*34600Sbostic getstring(Databuf, SZ_NAME); 977*34600Sbostic truncstring(Databuf); 978*34600Sbostic 979*34600Sbostic if ((loc = findname(Databuf, &Player)) >= 0L) 980*34600Sbostic /* found character */ 981*34600Sbostic { 982*34600Sbostic Echo = FALSE; 983*34600Sbostic 984*34600Sbostic for (loop = 0; loop < 2; ++loop) 985*34600Sbostic { 986*34600Sbostic /* prompt for password */ 987*34600Sbostic mvaddstr(11, 0, "Password ? "); 988*34600Sbostic getstring(Databuf, SZ_PASSWORD); 989*34600Sbostic if (strcmp(Databuf, Player.p_password) == 0) 990*34600Sbostic /* password good */ 991*34600Sbostic { 992*34600Sbostic Echo = TRUE; 993*34600Sbostic 994*34600Sbostic if (Player.p_status != S_OFF) 995*34600Sbostic /* player did not exit normally last time */ 996*34600Sbostic { 997*34600Sbostic clear(); 998*34600Sbostic addstr("Your character did not exit normally last time.\n"); 999*34600Sbostic addstr("If you think you have good cause to have your character saved,\n"); 1000*34600Sbostic printw("you may quit and mail your reason to '%s'.\n", WIZARD); 1001*34600Sbostic addstr("Otherwise, continuing spells certain death.\n"); 1002*34600Sbostic addstr("Do you want to quit ? "); 1003*34600Sbostic ch = getanswer("YN", FALSE); 1004*34600Sbostic if (ch == 'Y') 1005*34600Sbostic { 1006*34600Sbostic Player.p_status = S_HUNGUP; 1007*34600Sbostic writerecord(&Player, loc); 1008*34600Sbostic cleanup(TRUE); 1009*34600Sbostic /*NOTREACHED*/ 1010*34600Sbostic } 1011*34600Sbostic death("Stupidity"); 1012*34600Sbostic /*NOTREACHED*/ 1013*34600Sbostic } 1014*34600Sbostic return(loc); 1015*34600Sbostic } 1016*34600Sbostic else 1017*34600Sbostic mvaddstr(12, 0, "No good.\n"); 1018*34600Sbostic } 1019*34600Sbostic 1020*34600Sbostic Echo = TRUE; 1021*34600Sbostic } 1022*34600Sbostic else 1023*34600Sbostic mvaddstr(11, 0, "Not found.\n"); 1024*34600Sbostic 1025*34600Sbostic more(13); 1026*34600Sbostic return(-1L); 1027*34600Sbostic } 1028*34600Sbostic /**/ 1029*34600Sbostic /************************************************************************ 1030*34600Sbostic / 1031*34600Sbostic / FUNCTION NAME: neatstuff() 1032*34600Sbostic / 1033*34600Sbostic / FUNCTION: do random stuff 1034*34600Sbostic / 1035*34600Sbostic / AUTHOR: E. A. Estes, 3/3/86 1036*34600Sbostic / 1037*34600Sbostic / ARGUMENTS: none 1038*34600Sbostic / 1039*34600Sbostic / RETURN VALUE: none 1040*34600Sbostic / 1041*34600Sbostic / MODULES CALLED: collecttaxes(), floor(), wmove(), drandom(), infloat(), 1042*34600Sbostic / waddstr(), mvprintw(), getanswer() 1043*34600Sbostic / 1044*34600Sbostic / GLOBAL INPUTS: Player, *stdscr, *Statptr 1045*34600Sbostic / 1046*34600Sbostic / GLOBAL OUTPUTS: Player 1047*34600Sbostic / 1048*34600Sbostic / DESCRIPTION: 1049*34600Sbostic / Handle gurus, medics, etc. 1050*34600Sbostic / 1051*34600Sbostic /************************************************************************/ 1052*34600Sbostic 1053*34600Sbostic neatstuff() 1054*34600Sbostic { 1055*34600Sbostic double temp; /* for temporary calculations */ 1056*34600Sbostic int ch; /* input */ 1057*34600Sbostic 1058*34600Sbostic switch ((int) ROLL(0.0, 100.0)) 1059*34600Sbostic { 1060*34600Sbostic case 1: 1061*34600Sbostic case 2: 1062*34600Sbostic if (Player.p_poison > 0.0) 1063*34600Sbostic { 1064*34600Sbostic mvaddstr(4, 0, "You've found a medic! How much will you offer to be cured ? "); 1065*34600Sbostic temp = floor(infloat()); 1066*34600Sbostic if (temp < 0.0 || temp > Player.p_gold) 1067*34600Sbostic /* negative gold, or more than available */ 1068*34600Sbostic { 1069*34600Sbostic mvaddstr(6, 0, "He was not amused, and made you worse.\n"); 1070*34600Sbostic Player.p_poison += 1.0; 1071*34600Sbostic } 1072*34600Sbostic else if (drandom() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1)) 1073*34600Sbostic /* medic wants 1/2 of available gold */ 1074*34600Sbostic mvaddstr(5, 0, "Sorry, he wasn't interested.\n"); 1075*34600Sbostic else 1076*34600Sbostic { 1077*34600Sbostic mvaddstr(5, 0, "He accepted."); 1078*34600Sbostic Player.p_poison = MAX(0.0, Player.p_poison - 1.0); 1079*34600Sbostic Player.p_gold -= temp; 1080*34600Sbostic } 1081*34600Sbostic } 1082*34600Sbostic break; 1083*34600Sbostic 1084*34600Sbostic case 3: 1085*34600Sbostic mvaddstr(4, 0, "You've been caught raping and pillaging!\n"); 1086*34600Sbostic Player.p_experience += 4000.0; 1087*34600Sbostic Player.p_sin += 0.5; 1088*34600Sbostic break; 1089*34600Sbostic 1090*34600Sbostic case 4: 1091*34600Sbostic temp = ROLL(10.0, 75.0); 1092*34600Sbostic mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp); 1093*34600Sbostic ch = getanswer("NY", FALSE); 1094*34600Sbostic 1095*34600Sbostic if (ch == 'Y') 1096*34600Sbostic collecttaxes(temp, 0.0); 1097*34600Sbostic break; 1098*34600Sbostic 1099*34600Sbostic case 5: 1100*34600Sbostic if (Player.p_sin > 1.0) 1101*34600Sbostic { 1102*34600Sbostic mvaddstr(4, 0, "You've found a Holy Orb!\n"); 1103*34600Sbostic Player.p_sin -= 0.25; 1104*34600Sbostic } 1105*34600Sbostic break; 1106*34600Sbostic 1107*34600Sbostic case 6: 1108*34600Sbostic if (Player.p_poison < 1.0) 1109*34600Sbostic { 1110*34600Sbostic mvaddstr(4, 0, "You've been hit with a plague!\n"); 1111*34600Sbostic Player.p_poison += 1.0; 1112*34600Sbostic } 1113*34600Sbostic break; 1114*34600Sbostic 1115*34600Sbostic case 7: 1116*34600Sbostic mvaddstr(4, 0, "You've found some holy water.\n"); 1117*34600Sbostic ++Player.p_holywater; 1118*34600Sbostic break; 1119*34600Sbostic 1120*34600Sbostic case 8: 1121*34600Sbostic mvaddstr(4, 0, "You've met a Guru. . ."); 1122*34600Sbostic if (drandom() * Player.p_sin > 1.0) 1123*34600Sbostic addstr("You disgusted him with your sins!\n"); 1124*34600Sbostic else if (Player.p_poison > 0.0) 1125*34600Sbostic { 1126*34600Sbostic addstr("He looked kindly upon you, and cured you.\n"); 1127*34600Sbostic Player.p_poison = 0.0; 1128*34600Sbostic } 1129*34600Sbostic else 1130*34600Sbostic { 1131*34600Sbostic addstr("He rewarded you for your virtue.\n"); 1132*34600Sbostic Player.p_mana += 50.0; 1133*34600Sbostic Player.p_shield += 2.0; 1134*34600Sbostic } 1135*34600Sbostic break; 1136*34600Sbostic 1137*34600Sbostic case 9: 1138*34600Sbostic mvaddstr(4, 0, "You've found an amulet.\n"); 1139*34600Sbostic ++Player.p_amulets; 1140*34600Sbostic break; 1141*34600Sbostic 1142*34600Sbostic case 10: 1143*34600Sbostic if (Player.p_blindness) 1144*34600Sbostic { 1145*34600Sbostic mvaddstr(4, 0, "You've regained your sight!\n"); 1146*34600Sbostic Player.p_blindness = FALSE; 1147*34600Sbostic } 1148*34600Sbostic break; 1149*34600Sbostic 1150*34600Sbostic default: /* deal with poison */ 1151*34600Sbostic if (Player.p_poison > 0.0) 1152*34600Sbostic { 1153*34600Sbostic temp = Player.p_poison * Statptr->c_weakness 1154*34600Sbostic * Player.p_maxenergy / 600.0; 1155*34600Sbostic if (Player.p_energy > Player.p_maxenergy / 10.0 1156*34600Sbostic && temp + 5.0 < Player.p_energy) 1157*34600Sbostic Player.p_energy -= temp; 1158*34600Sbostic } 1159*34600Sbostic break; 1160*34600Sbostic } 1161*34600Sbostic } 1162*34600Sbostic /**/ 1163*34600Sbostic /************************************************************************ 1164*34600Sbostic / 1165*34600Sbostic / FUNCTION NAME: genchar() 1166*34600Sbostic / 1167*34600Sbostic / FUNCTION: generate a random character 1168*34600Sbostic / 1169*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 1170*34600Sbostic / 1171*34600Sbostic / ARGUMENTS: 1172*34600Sbostic / int type - ASCII value of character type to generate 1173*34600Sbostic / 1174*34600Sbostic / RETURN VALUE: none 1175*34600Sbostic / 1176*34600Sbostic / MODULES CALLED: floor(), drandom() 1177*34600Sbostic / 1178*34600Sbostic / GLOBAL INPUTS: Wizard, Player, Stattable[] 1179*34600Sbostic / 1180*34600Sbostic / GLOBAL OUTPUTS: Player 1181*34600Sbostic / 1182*34600Sbostic / DESCRIPTION: 1183*34600Sbostic / Use the lookup table for rolling stats. 1184*34600Sbostic / 1185*34600Sbostic /************************************************************************/ 1186*34600Sbostic 1187*34600Sbostic genchar(type) 1188*34600Sbostic int type; 1189*34600Sbostic { 1190*34600Sbostic register int subscript; /* used for subscripting into Stattable */ 1191*34600Sbostic register struct charstats *statptr;/* for pointing into Stattable */ 1192*34600Sbostic 1193*34600Sbostic subscript = type - '1'; 1194*34600Sbostic 1195*34600Sbostic if (subscript < C_MAGIC || subscript > C_EXPER) 1196*34600Sbostic if (subscript != C_SUPER || !Wizard) 1197*34600Sbostic /* fighter is default */ 1198*34600Sbostic subscript = C_FIGHTER; 1199*34600Sbostic 1200*34600Sbostic statptr = &Stattable[subscript]; 1201*34600Sbostic 1202*34600Sbostic Player.p_quickness = 1203*34600Sbostic ROLL(statptr->c_quickness.base, statptr->c_quickness.interval); 1204*34600Sbostic Player.p_strength = 1205*34600Sbostic ROLL(statptr->c_strength.base, statptr->c_strength.interval); 1206*34600Sbostic Player.p_mana = 1207*34600Sbostic ROLL(statptr->c_mana.base, statptr->c_mana.interval); 1208*34600Sbostic Player.p_maxenergy = 1209*34600Sbostic Player.p_energy = 1210*34600Sbostic ROLL(statptr->c_energy.base, statptr->c_energy.interval); 1211*34600Sbostic Player.p_brains = 1212*34600Sbostic ROLL(statptr->c_brains.base, statptr->c_brains.interval); 1213*34600Sbostic Player.p_magiclvl = 1214*34600Sbostic ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval); 1215*34600Sbostic 1216*34600Sbostic Player.p_type = subscript; 1217*34600Sbostic 1218*34600Sbostic if (Player.p_type == C_HALFLING) 1219*34600Sbostic /* give halfling some experience */ 1220*34600Sbostic Player.p_experience = ROLL(600.0, 200.0); 1221*34600Sbostic } 1222*34600Sbostic /**/ 1223*34600Sbostic /************************************************************************ 1224*34600Sbostic / 1225*34600Sbostic / FUNCTION NAME: playinit() 1226*34600Sbostic / 1227*34600Sbostic / FUNCTION: initialize for playing game 1228*34600Sbostic / 1229*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 1230*34600Sbostic / 1231*34600Sbostic / ARGUMENTS: none 1232*34600Sbostic / 1233*34600Sbostic / RETURN VALUE: none 1234*34600Sbostic / 1235*34600Sbostic / MODULES CALLED: signal(), wclear(), noecho(), crmode(), initscr(), 1236*34600Sbostic / wrefresh() 1237*34600Sbostic / 1238*34600Sbostic / GLOBAL INPUTS: *stdscr, ill_sig() 1239*34600Sbostic / 1240*34600Sbostic / GLOBAL OUTPUTS: Windows 1241*34600Sbostic / 1242*34600Sbostic / DESCRIPTION: 1243*34600Sbostic / Catch a bunch of signals, and turn on curses stuff. 1244*34600Sbostic / 1245*34600Sbostic /************************************************************************/ 1246*34600Sbostic 1247*34600Sbostic playinit() 1248*34600Sbostic { 1249*34600Sbostic /* catch/ingnore signals */ 1250*34600Sbostic 1251*34600Sbostic #ifdef BSD41 1252*34600Sbostic sigignore(SIGQUIT); 1253*34600Sbostic sigignore(SIGALRM); 1254*34600Sbostic sigignore(SIGTERM); 1255*34600Sbostic sigignore(SIGTSTP); 1256*34600Sbostic sigignore(SIGTTIN); 1257*34600Sbostic sigignore(SIGTTOU); 1258*34600Sbostic sighold(SIGINT); 1259*34600Sbostic sigset(SIGHUP, ill_sig); 1260*34600Sbostic sigset(SIGTRAP, ill_sig); 1261*34600Sbostic sigset(SIGIOT, ill_sig); 1262*34600Sbostic sigset(SIGEMT, ill_sig); 1263*34600Sbostic sigset(SIGFPE, ill_sig); 1264*34600Sbostic sigset(SIGBUS, ill_sig); 1265*34600Sbostic sigset(SIGSEGV, ill_sig); 1266*34600Sbostic sigset(SIGSYS, ill_sig); 1267*34600Sbostic sigset(SIGPIPE, ill_sig); 1268*34600Sbostic #endif 1269*34600Sbostic #ifdef BSD42 1270*34600Sbostic signal(SIGQUIT, ill_sig); 1271*34600Sbostic signal(SIGALRM, SIG_IGN); 1272*34600Sbostic signal(SIGTERM, SIG_IGN); 1273*34600Sbostic signal(SIGTSTP, SIG_IGN); 1274*34600Sbostic signal(SIGTTIN, SIG_IGN); 1275*34600Sbostic signal(SIGTTOU, SIG_IGN); 1276*34600Sbostic signal(SIGINT, ill_sig); 1277*34600Sbostic signal(SIGHUP, SIG_DFL); 1278*34600Sbostic signal(SIGTRAP, ill_sig); 1279*34600Sbostic signal(SIGIOT, ill_sig); 1280*34600Sbostic signal(SIGEMT, ill_sig); 1281*34600Sbostic signal(SIGFPE, ill_sig); 1282*34600Sbostic signal(SIGBUS, ill_sig); 1283*34600Sbostic signal(SIGSEGV, ill_sig); 1284*34600Sbostic signal(SIGSYS, ill_sig); 1285*34600Sbostic signal(SIGPIPE, ill_sig); 1286*34600Sbostic #endif 1287*34600Sbostic #ifdef SYS3 1288*34600Sbostic signal(SIGINT, SIG_IGN); 1289*34600Sbostic signal(SIGQUIT, SIG_IGN); 1290*34600Sbostic signal(SIGTERM, SIG_IGN); 1291*34600Sbostic signal(SIGALRM, SIG_IGN); 1292*34600Sbostic signal(SIGHUP, ill_sig); 1293*34600Sbostic signal(SIGTRAP, ill_sig); 1294*34600Sbostic signal(SIGIOT, ill_sig); 1295*34600Sbostic signal(SIGEMT, ill_sig); 1296*34600Sbostic signal(SIGFPE, ill_sig); 1297*34600Sbostic signal(SIGBUS, ill_sig); 1298*34600Sbostic signal(SIGSEGV, ill_sig); 1299*34600Sbostic signal(SIGSYS, ill_sig); 1300*34600Sbostic signal(SIGPIPE, ill_sig); 1301*34600Sbostic #endif 1302*34600Sbostic #ifdef SYS5 1303*34600Sbostic signal(SIGINT, SIG_IGN); 1304*34600Sbostic signal(SIGQUIT, SIG_IGN); 1305*34600Sbostic signal(SIGTERM, SIG_IGN); 1306*34600Sbostic signal(SIGALRM, SIG_IGN); 1307*34600Sbostic signal(SIGHUP, ill_sig); 1308*34600Sbostic signal(SIGTRAP, ill_sig); 1309*34600Sbostic signal(SIGIOT, ill_sig); 1310*34600Sbostic signal(SIGEMT, ill_sig); 1311*34600Sbostic signal(SIGFPE, ill_sig); 1312*34600Sbostic signal(SIGBUS, ill_sig); 1313*34600Sbostic signal(SIGSEGV, ill_sig); 1314*34600Sbostic signal(SIGSYS, ill_sig); 1315*34600Sbostic signal(SIGPIPE, ill_sig); 1316*34600Sbostic #endif 1317*34600Sbostic 1318*34600Sbostic initscr(); /* turn on curses */ 1319*34600Sbostic noecho(); /* do not echo input */ 1320*34600Sbostic crmode(); /* do not process erase, kill */ 1321*34600Sbostic clear(); 1322*34600Sbostic refresh(); 1323*34600Sbostic Windows = TRUE; /* mark the state */ 1324*34600Sbostic } 1325*34600Sbostic 1326*34600Sbostic /**/ 1327*34600Sbostic /************************************************************************ 1328*34600Sbostic / 1329*34600Sbostic / FUNCTION NAME: cleanup() 1330*34600Sbostic / 1331*34600Sbostic / FUNCTION: close some files, and maybe exit 1332*34600Sbostic / 1333*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 1334*34600Sbostic / 1335*34600Sbostic / ARGUMENTS: 1336*34600Sbostic / bool doexit - exit flag 1337*34600Sbostic / 1338*34600Sbostic / RETURN VALUE: none 1339*34600Sbostic / 1340*34600Sbostic / MODULES CALLED: exit(), wmove(), fclose(), endwin(), nocrmode(), wrefresh() 1341*34600Sbostic / 1342*34600Sbostic / GLOBAL INPUTS: *Energyvoidfp, LINES, *stdscr, Windows, *Monstfp, 1343*34600Sbostic / *Messagefp, *Playersfp 1344*34600Sbostic / 1345*34600Sbostic / GLOBAL OUTPUTS: none 1346*34600Sbostic / 1347*34600Sbostic / DESCRIPTION: 1348*34600Sbostic / Close all open files. If we are "in curses" terminate curses. 1349*34600Sbostic / If 'doexit' is set, exit, otherwise return. 1350*34600Sbostic / 1351*34600Sbostic /************************************************************************/ 1352*34600Sbostic 1353*34600Sbostic cleanup(doexit) 1354*34600Sbostic bool doexit; 1355*34600Sbostic { 1356*34600Sbostic if (Windows) 1357*34600Sbostic { 1358*34600Sbostic move(LINES - 2, 0); 1359*34600Sbostic refresh(); 1360*34600Sbostic nocrmode(); 1361*34600Sbostic endwin(); 1362*34600Sbostic } 1363*34600Sbostic 1364*34600Sbostic fclose(Playersfp); 1365*34600Sbostic fclose(Monstfp); 1366*34600Sbostic fclose(Messagefp); 1367*34600Sbostic fclose(Energyvoidfp); 1368*34600Sbostic 1369*34600Sbostic if (doexit) 1370*34600Sbostic exit(0); 1371*34600Sbostic /*NOTREACHED*/ 1372*34600Sbostic } 1373*34600Sbostic /**/ 1374*34600Sbostic #ifdef OK_TO_PLAY 1375*34600Sbostic #include <sys/types.h> 1376*34600Sbostic #include <utmp.h> /* used for counting users on system */ 1377*34600Sbostic 1378*34600Sbostic /************************************************************************ 1379*34600Sbostic / 1380*34600Sbostic / FUNCTION NAME: ok_to_play() 1381*34600Sbostic / 1382*34600Sbostic / FUNCTION: indicate whether playing is allowed 1383*34600Sbostic / 1384*34600Sbostic / AUTHOR: E. A. Estes, 12/4/85 1385*34600Sbostic / 1386*34600Sbostic / ARGUMENTS: none 1387*34600Sbostic / 1388*34600Sbostic / RETURN VALUE: 1389*34600Sbostic / FALSE if playing is not allowed 1390*34600Sbostic / TRUE if playing is allowed 1391*34600Sbostic / 1392*34600Sbostic / MODULES CALLED: time(), fread(), fopen(), fclose(), localtime() 1393*34600Sbostic / 1394*34600Sbostic / GLOBAL INPUTS: Wizard, Okcount 1395*34600Sbostic / 1396*34600Sbostic / GLOBAL OUTPUTS: Okcount 1397*34600Sbostic / 1398*34600Sbostic / DESCRIPTION: 1399*34600Sbostic / This function is provided to allow one to restrict access to the game. 1400*34600Sbostic / Tailor this routine as appropriate. 1401*34600Sbostic / Return FALSE if playing is not allowed at this time. 1402*34600Sbostic / 1403*34600Sbostic /************************************************************************/ 1404*34600Sbostic 1405*34600Sbostic ok_to_play() 1406*34600Sbostic { 1407*34600Sbostic register struct tm *tp; /* to get time of day */ 1408*34600Sbostic register int numusers = 0; /* number of users on system */ 1409*34600Sbostic FILE *fp; /* to open files */ 1410*34600Sbostic long now; /* present time */ 1411*34600Sbostic struct utmp ubuf; /* to read 'utmp' file */ 1412*34600Sbostic 1413*34600Sbostic if (Wizard) 1414*34600Sbostic /* wizard can always play */ 1415*34600Sbostic return(TRUE); 1416*34600Sbostic 1417*34600Sbostic if (Okcount >= 5) 1418*34600Sbostic Okcount = 0; 1419*34600Sbostic if (Okcount++ > 0) 1420*34600Sbostic /* only check every 5 times */ 1421*34600Sbostic return(TRUE); 1422*34600Sbostic 1423*34600Sbostic /* check time of day */ 1424*34600Sbostic time(&now); 1425*34600Sbostic tp = localtime(&now); 1426*34600Sbostic if (((tp->tm_hour > 8 && tp->tm_hour < 12) /* 8-noon */ 1427*34600Sbostic || (tp->tm_hour > 12 && tp->tm_hour < 16)) /* 1-4 pm */ 1428*34600Sbostic && (tp->tm_wday != 0 && tp->tm_wday != 6)) /* not a weekend */ 1429*34600Sbostic return(FALSE); 1430*34600Sbostic 1431*34600Sbostic /* check # of users */ 1432*34600Sbostic if ((fp = fopen("/etc/utmp", "r")) != NULL) 1433*34600Sbostic { 1434*34600Sbostic while (fread((char *) &ubuf, sizeof(ubuf), 1, fp) == 1) 1435*34600Sbostic #ifdef SYS5 1436*34600Sbostic if (ubuf.ut_type == USER_PROCESS) 1437*34600Sbostic #else 1438*34600Sbostic if (ubuf.ut_name[0] != '\0') 1439*34600Sbostic #endif 1440*34600Sbostic ++numusers; 1441*34600Sbostic fclose(fp); 1442*34600Sbostic 1443*34600Sbostic if (numusers > N_MAXUSERS) 1444*34600Sbostic return(FALSE); 1445*34600Sbostic } 1446*34600Sbostic return(TRUE); 1447*34600Sbostic } 1448*34600Sbostic #endif 1449