main.c revision 1.8
1/* $NetBSD: main.c,v 1.8 1999/09/08 21:57:19 jsm Exp $ */ 2 3/* 4 * Phantasia 3.3.2 -- Interterminal fantasy game 5 * 6 * Edward A. Estes 7 * AT&T, March 12, 1986 8 */ 9 10/* DISCLAIMER: 11 * 12 * This game is distributed for free as is. It is not guaranteed to work 13 * in every conceivable environment. It is not even guaranteed to work 14 * in ANY environment. 15 * 16 * This game is distributed without notice of copyright, therefore it 17 * may be used in any manner the recipient sees fit. However, the 18 * author assumes no responsibility for maintaining or revising this 19 * game, in its original form, or any derivitives thereof. 20 * 21 * The author shall not be responsible for any loss, cost, or damage, 22 * including consequential damage, caused by reliance on this material. 23 * 24 * The author makes no warranties, express or implied, including warranties 25 * of merchantability or fitness for a particular purpose or use. 26 * 27 * AT&T is in no way connected with this game. 28 */ 29 30#include <sys/types.h> 31#include <pwd.h> 32 33/* 34 * The program allocates as much file space as it needs to store characters, 35 * so the possibility exists for the character file to grow without bound. 36 * The file is purged upon normal entry to try to avoid that problem. 37 * A similar problem exists for energy voids. To alleviate the problem here, 38 * the void file is cleared with every new king, and a limit is placed 39 * on the size of the energy void file. 40 */ 41 42/* 43 * Put one line of text into the file 'motd' for announcements, etc. 44 */ 45 46/* 47 * The scoreboard file is updated when someone dies, and keeps track 48 * of the highest character to date for that login. 49 * Being purged from the character file does not cause the scoreboard 50 * to be updated. 51 */ 52 53 54/* 55 * main.c Main routines for Phantasia 56 */ 57 58#include "include.h" 59 60int main __P((int, char **)); 61 62int 63main(argc, argv) 64 int argc; 65 char **argv; 66{ 67 bool noheader = FALSE; /* set if don't want header */ 68 bool headeronly = FALSE; /* set if only want header */ 69 bool examine = FALSE; /* set if examine a character */ 70 time_t seconds; /* for time of day */ 71 double dtemp; /* for temporary calculations */ 72 73 initialstate(); /* init globals */ 74 75 /* process arguments */ 76 while (--argc && (*++argv)[0] == '-') 77 switch ((*argv)[1]) { 78 case 's': /* short */ 79 noheader = TRUE; 80 break; 81 82 case 'H': /* Header */ 83 headeronly = TRUE; 84 break; 85 86 case 'a': /* all users */ 87 activelist(); 88 cleanup(TRUE); 89 /* NOTREACHED */ 90 91 case 'p': /* purge old players */ 92 purgeoldplayers(); 93 cleanup(TRUE); 94 /* NOTREACHED */ 95 96 case 'S': /* set 'Wizard' */ 97 Wizard = !getuid(); 98 break; 99 100 case 'x': /* examine */ 101 examine = TRUE; 102 break; 103 104 case 'm': /* monsters */ 105 monstlist(); 106 cleanup(TRUE); 107 /* NOTREACHED */ 108 109 case 'b': /* scoreboard */ 110 scorelist(); 111 cleanup(TRUE); 112 /* NOTREACHED */ 113 } 114 115 if (!isatty(0)) /* don't let non-tty's play */ 116 cleanup(TRUE); 117 /* NOTREACHED */ 118 119 playinit(); /* set up to catch signals, init curses */ 120 121 if (examine) { 122 changestats(FALSE); 123 cleanup(TRUE); 124 /* NOTREACHED */ 125 } 126 if (!noheader) { 127 titlelist(); 128 purgeoldplayers(); /* clean up old characters */ 129 } 130 if (headeronly) 131 cleanup(TRUE); 132 /* NOTREACHED */ 133 134 do 135 /* get the player structure filled */ 136 { 137 Fileloc = -1L; 138 139 mvaddstr(22, 17, "Do you have a character to run [Q = Quit] ? "); 140 141 switch (getanswer("NYQ", FALSE)) { 142 case 'Y': 143 Fileloc = recallplayer(); 144 break; 145 146 case 'Q': 147 cleanup(TRUE); 148 /* NOTREACHED */ 149 150 default: 151 Fileloc = rollnewplayer(); 152 break; 153 } 154 clear(); 155 } 156 while (Fileloc < 0L); 157 158 if (Player.p_level > 5.0) 159 /* low level players have long timeout */ 160 Timeout = TRUE; 161 162 /* update some important player statistics */ 163 strcpy(Player.p_login, Login); 164 time(&seconds); 165 Player.p_lastused = localtime(&seconds)->tm_yday; 166 Player.p_status = S_PLAYING; 167 writerecord(&Player, Fileloc); 168 169 Statptr = &Stattable[Player.p_type]; /* initialize pointer */ 170 171 /* catch interrupts */ 172#ifdef BSD41 173 sigset(SIGINT, interrupt); 174#endif 175#ifdef BSD42 176 signal(SIGINT, interrupt); 177#endif 178#ifdef SYS3 179 signal(SIGINT, interrupt); 180#endif 181#ifdef SYS5 182 signal(SIGINT, interrupt); 183#endif 184 185 altercoordinates(Player.p_x, Player.p_y, A_FORCED); /* set some flags */ 186 187 clear(); 188 189 for (;;) 190 /* loop forever, processing input */ 191 { 192 193 adjuststats(); /* cleanup stats */ 194 195 if (Throne && Player.p_crowns == 0 && Player.p_specialtype != SC_KING) 196 /* not allowed on throne -- move */ 197 { 198 mvaddstr(5, 0, "You're not allowed in the Lord's Chamber without a crown.\n"); 199 altercoordinates(0.0, 0.0, A_NEAR); 200 } 201 checktampered();/* check for energy voids, etc. */ 202 203 if (Player.p_status != S_CLOAKED 204 /* not cloaked */ 205 && (dtemp = fabs(Player.p_x)) == fabs(Player.p_y) 206 /* |x| = |y| */ 207 && !Throne) 208 /* not on throne */ 209 { 210 dtemp = sqrt(dtemp / 100.0); 211 if (floor(dtemp) == dtemp) 212 /* |x| / 100 == n*n; at a trading post */ 213 { 214 tradingpost(); 215 clear(); 216 } 217 } 218 checkbattle(); /* check for player to player battle */ 219 neatstuff(); /* gurus, medics, etc. */ 220 221 if (Player.p_status == S_CLOAKED) { 222 /* costs 3 mana per turn to be cloaked */ 223 if (Player.p_mana > 3.0) 224 Player.p_mana -= 3.0; 225 else 226 /* ran out of mana, uncloak */ 227 { 228 Player.p_status = S_PLAYING; 229 Changed = TRUE; 230 } 231 } 232 233 if (Player.p_status != S_PLAYING && Player.p_status != S_CLOAKED) 234 /* change status back to S_PLAYING */ 235 { 236 Player.p_status = S_PLAYING; 237 Changed = TRUE; 238 } 239 if (Changed) 240 /* update file only if important stuff has changed */ 241 { 242 writerecord(&Player, Fileloc); 243 Changed = FALSE; 244 continue; 245 } 246 readmessage(); /* read message, if any */ 247 248 displaystats(); /* print statistics */ 249 250 move(6, 0); 251 252 if (Throne) 253 /* maybe make king, print prompt, etc. */ 254 throneroom(); 255 256 /* print status line */ 257 addstr("1:Move 2:Players 3:Talk 4:Stats 5:Quit "); 258 if (Player.p_level >= MEL_CLOAK && Player.p_magiclvl >= ML_CLOAK) 259 addstr("6:Cloak "); 260 if (Player.p_level >= MEL_TELEPORT && Player.p_magiclvl >= ML_TELEPORT) 261 addstr("7:Teleport "); 262 if (Player.p_specialtype >= SC_COUNCIL || Wizard) 263 addstr("8:Intervene "); 264 265 procmain(); /* process input */ 266 } 267} 268 269void 270initialstate() 271{ 272 Beyond = FALSE; 273 Marsh = FALSE; 274 Throne = FALSE; 275 Changed = FALSE; 276 Wizard = FALSE; 277 Timeout = FALSE; 278 Users = 0; 279 Windows = FALSE; 280 Echo = TRUE; 281 282 /* setup login name */ 283 if ((Login = getlogin()) == NULL) 284 Login = getpwuid(getuid())->pw_name; 285 286 /* open some files */ 287 if ((Playersfp = fopen(_PATH_PEOPLE, "r+")) == NULL) 288 error(_PATH_PEOPLE); 289 /* NOTREACHED */ 290 291 if ((Monstfp = fopen(_PATH_MONST, "r+")) == NULL) 292 error(_PATH_MONST); 293 /* NOTREACHED */ 294 295 if ((Messagefp = fopen(_PATH_MESS, "r")) == NULL) 296 error(_PATH_MESS); 297 /* NOTREACHED */ 298 299 if ((Energyvoidfp = fopen(_PATH_VOID, "r+")) == NULL) 300 error(_PATH_VOID); 301 /* NOTREACHED */ 302 303 srandom((unsigned) time(NULL)); /* prime random numbers */ 304} 305 306long 307rollnewplayer() 308{ 309 int chartype; /* character type */ 310 int ch; /* input */ 311 312 initplayer(&Player); /* initialize player structure */ 313 314 clear(); 315 mvaddstr(4, 21, "Which type of character do you want:"); 316 mvaddstr(8, 4, 317"1:Magic User 2:Fighter 3:Elf 4:Dwarf 5:Halfling 6:Experimento "); 318 if (Wizard) { 319 addstr("7:Super ? "); 320 chartype = getanswer("1234567", FALSE); 321 } else { 322 addstr("? "); 323 chartype = getanswer("123456", FALSE); 324 } 325 326 do { 327 genchar(chartype); /* roll up a character */ 328 329 /* print out results */ 330 mvprintw(12, 14, 331 "Strength : %2.0f Quickness: %2.0f Mana : %2.0f\n", 332 Player.p_strength, Player.p_quickness, Player.p_mana); 333 mvprintw(13, 14, 334 "Energy Level: %2.0f Brains : %2.0f Magic Level: %2.0f\n", 335 Player.p_energy, Player.p_brains, Player.p_magiclvl); 336 337 if (Player.p_type == C_EXPER || Player.p_type == C_SUPER) 338 break; 339 340 mvaddstr(14, 14, "Type '1' to keep >"); 341 ch = getanswer(" ", TRUE); 342 } 343 while (ch != '1'); 344 345 if (Player.p_type == C_EXPER || Player.p_type == C_SUPER) 346 /* get coordinates for experimento */ 347 for (;;) { 348 mvaddstr(16, 0, "Enter the X Y coordinates of your experimento ? "); 349 getstring(Databuf, SZ_DATABUF); 350 sscanf(Databuf, "%lf %lf", &Player.p_x, &Player.p_y); 351 352 if (fabs(Player.p_x) > D_EXPER || fabs(Player.p_y) > D_EXPER) 353 mvaddstr(17, 0, "Invalid coordinates. Try again.\n"); 354 else 355 break; 356 } 357 358 for (;;) 359 /* name the new character */ 360 { 361 mvprintw(18, 0, 362 "Give your character a name [up to %d characters] ? ", SZ_NAME - 1); 363 getstring(Player.p_name, SZ_NAME); 364 truncstring(Player.p_name); /* remove trailing blanks */ 365 366 if (Player.p_name[0] == '\0') 367 /* no null names */ 368 mvaddstr(19, 0, "Invalid name."); 369 else 370 if (findname(Player.p_name, &Other) >= 0L) 371 /* cannot have duplicate names */ 372 mvaddstr(19, 0, "Name already in use."); 373 else 374 /* name is acceptable */ 375 break; 376 377 addstr(" Pick another.\n"); 378 } 379 380 /* get a password for character */ 381 Echo = FALSE; 382 383 do { 384 mvaddstr(20, 0, "Give your character a password [up to 8 characters] ? "); 385 getstring(Player.p_password, SZ_PASSWORD); 386 mvaddstr(21, 0, "Enter again to verify: "); 387 getstring(Databuf, SZ_PASSWORD); 388 } 389 while (strcmp(Player.p_password, Databuf) != 0); 390 391 Echo = TRUE; 392 393 return (allocrecord()); 394} 395 396void 397procmain() 398{ 399 int ch; /* input */ 400 double x; /* desired new x coordinate */ 401 double y; /* desired new y coordinate */ 402 double temp; /* for temporary calculations */ 403 FILE *fp; /* for opening files */ 404 int loop; /* a loop counter */ 405 bool hasmoved = FALSE; /* set if player has moved */ 406 407 ch = inputoption(); 408 mvaddstr(4, 0, "\n\n"); /* clear status area */ 409 410 move(7, 0); 411 clrtobot(); /* clear data on bottom area of screen */ 412 413 if (Player.p_specialtype == SC_VALAR && (ch == '1' || ch == '7')) 414 /* valar cannot move */ 415 ch = ' '; 416 417 switch (ch) { 418 case 'K': /* move up/north */ 419 case 'N': 420 x = Player.p_x; 421 y = Player.p_y + MAXMOVE(); 422 hasmoved = TRUE; 423 break; 424 425 case 'J': /* move down/south */ 426 case 'S': 427 x = Player.p_x; 428 y = Player.p_y - MAXMOVE(); 429 hasmoved = TRUE; 430 break; 431 432 case 'L': /* move right/east */ 433 case 'E': 434 x = Player.p_x + MAXMOVE(); 435 y = Player.p_y; 436 hasmoved = TRUE; 437 break; 438 439 case 'H': /* move left/west */ 440 case 'W': 441 x = Player.p_x - MAXMOVE(); 442 y = Player.p_y; 443 hasmoved = TRUE; 444 break; 445 446 default: /* rest */ 447 Player.p_energy += (Player.p_maxenergy + Player.p_shield) / 15.0 448 + Player.p_level / 3.0 + 2.0; 449 Player.p_energy = 450 MIN(Player.p_energy, Player.p_maxenergy + Player.p_shield); 451 452 if (Player.p_status != S_CLOAKED) 453 /* cannot find mana if cloaked */ 454 { 455 Player.p_mana += (Circle + Player.p_level) / 4.0; 456 457 if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne) 458 /* wandering monster */ 459 encounter(-1); 460 } 461 break; 462 463 case 'X': /* change/examine a character */ 464 changestats(TRUE); 465 break; 466 467 case '1': /* move */ 468 for (loop = 3; loop; --loop) { 469 mvaddstr(4, 0, "X Y Coordinates ? "); 470 getstring(Databuf, SZ_DATABUF); 471 472 if (sscanf(Databuf, "%lf %lf", &x, &y) != 2) 473 mvaddstr(5, 0, "Try again\n"); 474 else 475 if (distance(Player.p_x, x, Player.p_y, y) > MAXMOVE()) 476 ILLMOVE(); 477 else { 478 hasmoved = TRUE; 479 break; 480 } 481 } 482 break; 483 484 case '2': /* players */ 485 userlist(TRUE); 486 break; 487 488 case '3': /* message */ 489 mvaddstr(4, 0, "Message ? "); 490 getstring(Databuf, SZ_DATABUF); 491 /* we open the file for writing to erase any data which is 492 * already there */ 493 fp = fopen(_PATH_MESS, "w"); 494 if (Databuf[0] != '\0') 495 fprintf(fp, "%s: %s", Player.p_name, Databuf); 496 fclose(fp); 497 break; 498 499 case '4': /* stats */ 500 allstatslist(); 501 break; 502 503 case '5': /* good-bye */ 504 leavegame(); 505 /* NOTREACHED */ 506 507 case '6': /* cloak */ 508 if (Player.p_level < MEL_CLOAK || Player.p_magiclvl < ML_CLOAK) 509 ILLCMD(); 510 else 511 if (Player.p_status == S_CLOAKED) 512 Player.p_status = S_PLAYING; 513 else 514 if (Player.p_mana < MM_CLOAK) 515 mvaddstr(5, 0, "No mana left.\n"); 516 else { 517 Changed = TRUE; 518 Player.p_mana -= MM_CLOAK; 519 Player.p_status = S_CLOAKED; 520 } 521 break; 522 523 case '7': /* teleport */ 524 /* 525 * conditions for teleport 526 * - 20 per (level plus magic level) 527 * - OR council of the wise or valar or ex-valar 528 * - OR transport from throne 529 * transports from throne cost no mana 530 */ 531 if (Player.p_level < MEL_TELEPORT || Player.p_magiclvl < ML_TELEPORT) 532 ILLCMD(); 533 else 534 for (loop = 3; loop; --loop) { 535 mvaddstr(4, 0, "X Y Coordinates ? "); 536 getstring(Databuf, SZ_DATABUF); 537 538 if (sscanf(Databuf, "%lf %lf", &x, &y) == 2) { 539 temp = distance(Player.p_x, x, Player.p_y, y); 540 if (!Throne 541 /* can transport anywhere from throne */ 542 && Player.p_specialtype <= SC_COUNCIL 543 /* council, valar can transport 544 * anywhere */ 545 && temp > (Player.p_level + Player.p_magiclvl) * 20.0) 546 /* can only move 20 per exp. 547 * level + mag. level */ 548 ILLMOVE(); 549 else { 550 temp = (temp / 75.0 + 1.0) * 20.0; /* mana used */ 551 552 if (!Throne && temp > Player.p_mana) 553 mvaddstr(5, 0, "Not enough power for that distance.\n"); 554 else { 555 if (!Throne) 556 Player.p_mana -= temp; 557 hasmoved = TRUE; 558 break; 559 } 560 } 561 } 562 } 563 break; 564 565 case 'C': 566 case '9': /* monster */ 567 if (Throne) 568 /* no monsters while on throne */ 569 mvaddstr(5, 0, "No monsters in the chamber!\n"); 570 else 571 if (Player.p_specialtype != SC_VALAR) 572 /* the valar cannot call monsters */ 573 { 574 Player.p_sin += 1e-6; 575 encounter(-1); 576 } 577 break; 578 579 case '0': /* decree */ 580 if (Wizard || (Player.p_specialtype == SC_KING && Throne)) 581 /* kings must be on throne to decree */ 582 dotampered(); 583 else 584 ILLCMD(); 585 break; 586 587 case '8': /* intervention */ 588 if (Wizard || Player.p_specialtype >= SC_COUNCIL) 589 dotampered(); 590 else 591 ILLCMD(); 592 break; 593 } 594 595 if (hasmoved) 596 /* player has moved -- alter coordinates, and do random 597 * monster */ 598 { 599 altercoordinates(x, y, A_SPECIFIC); 600 601 if (drandom() < 0.2 && Player.p_status == S_PLAYING && !Throne) 602 encounter(-1); 603 } 604} 605 606void 607titlelist() 608{ 609 FILE *fp; /* used for opening various files */ 610 bool councilfound = FALSE; /* set if we find a member of the 611 * council */ 612 bool kingfound = FALSE; /* set if we find a king */ 613 double hiexp, nxtexp; /* used for finding the two highest players */ 614 double hilvl, nxtlvl; /* used for finding the two highest players */ 615 char hiname[21], nxtname[21]; /* used for finding the two 616 * highest players */ 617 618 nxtexp = 0; 619 mvaddstr(0, 14, 620 "W e l c o m e t o P h a n t a s i a (vers. 3.3.2)!"); 621 622 /* print message of the day */ 623 if ((fp = fopen(_PATH_MOTD, "r")) != NULL 624 && fgets(Databuf, SZ_DATABUF, fp) != NULL) { 625 mvaddstr(2, 40 - strlen(Databuf) / 2, Databuf); 626 fclose(fp); 627 } 628 /* search for king */ 629 fseek(Playersfp, 0L, SEEK_SET); 630 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 631 if (Other.p_specialtype == SC_KING && 632 Other.p_status != S_NOTUSED) 633 /* found the king */ 634 { 635 sprintf(Databuf, "The present ruler is %s Level:%.0f", 636 Other.p_name, Other.p_level); 637 mvaddstr(4, 40 - strlen(Databuf) / 2, Databuf); 638 kingfound = TRUE; 639 break; 640 } 641 if (!kingfound) 642 mvaddstr(4, 24, "There is no ruler at this time."); 643 644 /* search for valar */ 645 fseek(Playersfp, 0L, SEEK_SET); 646 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 647 if (Other.p_specialtype == SC_VALAR && Other.p_status != S_NOTUSED) 648 /* found the valar */ 649 { 650 sprintf(Databuf, "The Valar is %s Login: %s", Other.p_name, Other.p_login); 651 mvaddstr(6, 40 - strlen(Databuf) / 2, Databuf); 652 break; 653 } 654 /* search for council of the wise */ 655 fseek(Playersfp, 0L, SEEK_SET); 656 Lines = 10; 657 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 658 if (Other.p_specialtype == SC_COUNCIL && Other.p_status != S_NOTUSED) 659 /* found a member of the council */ 660 { 661 if (!councilfound) { 662 mvaddstr(8, 30, "Council of the Wise:"); 663 councilfound = TRUE; 664 } 665 /* This assumes a finite (<=5) number of C.O.W.: */ 666 sprintf(Databuf, "%s Login: %s", Other.p_name, Other.p_login); 667 mvaddstr(Lines++, 40 - strlen(Databuf) / 2, Databuf); 668 } 669 /* search for the two highest players */ 670 nxtname[0] = hiname[0] = '\0'; 671 hiexp = 0.0; 672 nxtlvl = hilvl = 0; 673 674 fseek(Playersfp, 0L, SEEK_SET); 675 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 676 if (Other.p_experience > hiexp && Other.p_specialtype <= SC_KING && Other.p_status != S_NOTUSED) 677 /* highest found so far */ 678 { 679 nxtexp = hiexp; 680 hiexp = Other.p_experience; 681 nxtlvl = hilvl; 682 hilvl = Other.p_level; 683 strcpy(nxtname, hiname); 684 strcpy(hiname, Other.p_name); 685 } else 686 if (Other.p_experience > nxtexp 687 && Other.p_specialtype <= SC_KING 688 && Other.p_status != S_NOTUSED) 689 /* next highest found so far */ 690 { 691 nxtexp = Other.p_experience; 692 nxtlvl = Other.p_level; 693 strcpy(nxtname, Other.p_name); 694 } 695 mvaddstr(15, 28, "Highest characters are:"); 696 sprintf(Databuf, "%s Level:%.0f and %s Level:%.0f", 697 hiname, hilvl, nxtname, nxtlvl); 698 mvaddstr(17, 40 - strlen(Databuf) / 2, Databuf); 699 700 /* print last to die */ 701 if ((fp = fopen(_PATH_LASTDEAD, "r")) != NULL 702 && fgets(Databuf, SZ_DATABUF, fp) != NULL) { 703 mvaddstr(19, 25, "The last character to die was:"); 704 mvaddstr(20, 40 - strlen(Databuf) / 2, Databuf); 705 fclose(fp); 706 } 707 refresh(); 708} 709 710long 711recallplayer() 712{ 713 long loc = 0L; /* location in player file */ 714 int loop; /* loop counter */ 715 int ch; /* input */ 716 717 clear(); 718 mvprintw(10, 0, "What was your character's name ? "); 719 getstring(Databuf, SZ_NAME); 720 truncstring(Databuf); 721 722 if ((loc = findname(Databuf, &Player)) >= 0L) 723 /* found character */ 724 { 725 Echo = FALSE; 726 727 for (loop = 0; loop < 2; ++loop) { 728 /* prompt for password */ 729 mvaddstr(11, 0, "Password ? "); 730 getstring(Databuf, SZ_PASSWORD); 731 if (strcmp(Databuf, Player.p_password) == 0) 732 /* password good */ 733 { 734 Echo = TRUE; 735 736 if (Player.p_status != S_OFF) 737 /* player did not exit normally last 738 * time */ 739 { 740 clear(); 741 addstr("Your character did not exit normally last time.\n"); 742 addstr("If you think you have good cause to have your character saved,\n"); 743 printw("you may quit and mail your reason to 'root'.\n"); 744 addstr("Otherwise, continuing spells certain death.\n"); 745 addstr("Do you want to quit ? "); 746 ch = getanswer("YN", FALSE); 747 if (ch == 'Y') { 748 Player.p_status = S_HUNGUP; 749 writerecord(&Player, loc); 750 cleanup(TRUE); 751 /* NOTREACHED */ 752 } 753 death("Stupidity"); 754 /* NOTREACHED */ 755 } 756 return (loc); 757 } else 758 mvaddstr(12, 0, "No good.\n"); 759 } 760 761 Echo = TRUE; 762 } else 763 mvaddstr(11, 0, "Not found.\n"); 764 765 more(13); 766 return (-1L); 767} 768 769void 770neatstuff() 771{ 772 double temp; /* for temporary calculations */ 773 int ch; /* input */ 774 775 switch ((int) ROLL(0.0, 100.0)) { 776 case 1: 777 case 2: 778 if (Player.p_poison > 0.0) { 779 mvaddstr(4, 0, "You've found a medic! How much will you offer to be cured ? "); 780 temp = floor(infloat()); 781 if (temp < 0.0 || temp > Player.p_gold) 782 /* negative gold, or more than available */ 783 { 784 mvaddstr(6, 0, "He was not amused, and made you worse.\n"); 785 Player.p_poison += 1.0; 786 } else 787 if (drandom() / 2.0 > (temp + 1.0) / MAX(Player.p_gold, 1)) 788 /* medic wants 1/2 of available gold */ 789 mvaddstr(5, 0, "Sorry, he wasn't interested.\n"); 790 else { 791 mvaddstr(5, 0, "He accepted."); 792 Player.p_poison = MAX(0.0, Player.p_poison - 1.0); 793 Player.p_gold -= temp; 794 } 795 } 796 break; 797 798 case 3: 799 mvaddstr(4, 0, "You've been caught raping and pillaging!\n"); 800 Player.p_experience += 4000.0; 801 Player.p_sin += 0.5; 802 break; 803 804 case 4: 805 temp = ROLL(10.0, 75.0); 806 mvprintw(4, 0, "You've found %.0f gold pieces, want them ? ", temp); 807 ch = getanswer("NY", FALSE); 808 809 if (ch == 'Y') 810 collecttaxes(temp, 0.0); 811 break; 812 813 case 5: 814 if (Player.p_sin > 1.0) { 815 mvaddstr(4, 0, "You've found a Holy Orb!\n"); 816 Player.p_sin -= 0.25; 817 } 818 break; 819 820 case 6: 821 if (Player.p_poison < 1.0) { 822 mvaddstr(4, 0, "You've been hit with a plague!\n"); 823 Player.p_poison += 1.0; 824 } 825 break; 826 827 case 7: 828 mvaddstr(4, 0, "You've found some holy water.\n"); 829 ++Player.p_holywater; 830 break; 831 832 case 8: 833 mvaddstr(4, 0, "You've met a Guru. . ."); 834 if (drandom() * Player.p_sin > 1.0) 835 addstr("You disgusted him with your sins!\n"); 836 else 837 if (Player.p_poison > 0.0) { 838 addstr("He looked kindly upon you, and cured you.\n"); 839 Player.p_poison = 0.0; 840 } else { 841 addstr("He rewarded you for your virtue.\n"); 842 Player.p_mana += 50.0; 843 Player.p_shield += 2.0; 844 } 845 break; 846 847 case 9: 848 mvaddstr(4, 0, "You've found an amulet.\n"); 849 ++Player.p_amulets; 850 break; 851 852 case 10: 853 if (Player.p_blindness) { 854 mvaddstr(4, 0, "You've regained your sight!\n"); 855 Player.p_blindness = FALSE; 856 } 857 break; 858 859 default: /* deal with poison */ 860 if (Player.p_poison > 0.0) { 861 temp = Player.p_poison * Statptr->c_weakness 862 * Player.p_maxenergy / 600.0; 863 if (Player.p_energy > Player.p_maxenergy / 10.0 864 && temp + 5.0 < Player.p_energy) 865 Player.p_energy -= temp; 866 } 867 break; 868 } 869} 870 871void 872genchar(type) 873 int type; 874{ 875 int subscript; /* used for subscripting into Stattable */ 876 const struct charstats *statptr; /* for pointing into Stattable */ 877 878 subscript = type - '1'; 879 880 if (subscript < C_MAGIC || subscript > C_EXPER) 881 if (subscript != C_SUPER || !Wizard) 882 /* fighter is default */ 883 subscript = C_FIGHTER; 884 885 statptr = &Stattable[subscript]; 886 887 Player.p_quickness = 888 ROLL(statptr->c_quickness.base, statptr->c_quickness.interval); 889 Player.p_strength = 890 ROLL(statptr->c_strength.base, statptr->c_strength.interval); 891 Player.p_mana = 892 ROLL(statptr->c_mana.base, statptr->c_mana.interval); 893 Player.p_maxenergy = 894 Player.p_energy = 895 ROLL(statptr->c_energy.base, statptr->c_energy.interval); 896 Player.p_brains = 897 ROLL(statptr->c_brains.base, statptr->c_brains.interval); 898 Player.p_magiclvl = 899 ROLL(statptr->c_magiclvl.base, statptr->c_magiclvl.interval); 900 901 Player.p_type = subscript; 902 903 if (Player.p_type == C_HALFLING) 904 /* give halfling some experience */ 905 Player.p_experience = ROLL(600.0, 200.0); 906} 907 908void 909playinit() 910{ 911 /* catch/ingnore signals */ 912 913#ifdef BSD41 914 sigignore(SIGQUIT); 915 sigignore(SIGALRM); 916 sigignore(SIGTERM); 917 sigignore(SIGTSTP); 918 sigignore(SIGTTIN); 919 sigignore(SIGTTOU); 920 sighold(SIGINT); 921 sigset(SIGHUP, ill_sig); 922 sigset(SIGTRAP, ill_sig); 923 sigset(SIGIOT, ill_sig); 924 sigset(SIGEMT, ill_sig); 925 sigset(SIGFPE, ill_sig); 926 sigset(SIGBUS, ill_sig); 927 sigset(SIGSEGV, ill_sig); 928 sigset(SIGSYS, ill_sig); 929 sigset(SIGPIPE, ill_sig); 930#endif 931#ifdef BSD42 932 signal(SIGQUIT, ill_sig); 933 signal(SIGALRM, SIG_IGN); 934 signal(SIGTERM, SIG_IGN); 935 signal(SIGTSTP, SIG_IGN); 936 signal(SIGTTIN, SIG_IGN); 937 signal(SIGTTOU, SIG_IGN); 938 signal(SIGINT, ill_sig); 939 signal(SIGHUP, SIG_DFL); 940 signal(SIGTRAP, ill_sig); 941 signal(SIGIOT, ill_sig); 942 signal(SIGEMT, ill_sig); 943 signal(SIGFPE, ill_sig); 944 signal(SIGBUS, ill_sig); 945 signal(SIGSEGV, ill_sig); 946 signal(SIGSYS, ill_sig); 947 signal(SIGPIPE, ill_sig); 948#endif 949#ifdef SYS3 950 signal(SIGINT, SIG_IGN); 951 signal(SIGQUIT, SIG_IGN); 952 signal(SIGTERM, SIG_IGN); 953 signal(SIGALRM, SIG_IGN); 954 signal(SIGHUP, ill_sig); 955 signal(SIGTRAP, ill_sig); 956 signal(SIGIOT, ill_sig); 957 signal(SIGEMT, ill_sig); 958 signal(SIGFPE, ill_sig); 959 signal(SIGBUS, ill_sig); 960 signal(SIGSEGV, ill_sig); 961 signal(SIGSYS, ill_sig); 962 signal(SIGPIPE, ill_sig); 963#endif 964#ifdef SYS5 965 signal(SIGINT, SIG_IGN); 966 signal(SIGQUIT, SIG_IGN); 967 signal(SIGTERM, SIG_IGN); 968 signal(SIGALRM, SIG_IGN); 969 signal(SIGHUP, ill_sig); 970 signal(SIGTRAP, ill_sig); 971 signal(SIGIOT, ill_sig); 972 signal(SIGEMT, ill_sig); 973 signal(SIGFPE, ill_sig); 974 signal(SIGBUS, ill_sig); 975 signal(SIGSEGV, ill_sig); 976 signal(SIGSYS, ill_sig); 977 signal(SIGPIPE, ill_sig); 978#endif 979 980 initscr(); /* turn on curses */ 981 noecho(); /* do not echo input */ 982 crmode(); /* do not process erase, kill */ 983 clear(); 984 refresh(); 985 Windows = TRUE; /* mark the state */ 986} 987 988void 989cleanup(doexit) 990 int doexit; 991{ 992 if (Windows) { 993 move(LINES - 2, 0); 994 refresh(); 995 nocrmode(); 996 endwin(); 997 } 998 fclose(Playersfp); 999 fclose(Monstfp); 1000 fclose(Messagefp); 1001 fclose(Energyvoidfp); 1002 1003 if (doexit) 1004 exit(0); 1005 /* NOTREACHED */ 1006} 1007