1 /* $NetBSD: interplayer.c,v 1.12 2009/08/31 08:27:16 dholland Exp $ */ 2 3 /* 4 * interplayer.c - player to player routines for Phantasia 5 */ 6 7 #include <math.h> 8 #include <setjmp.h> 9 #include <stdio.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 #include "macros.h" 14 #include "phantdefs.h" 15 #include "phantstruct.h" 16 #include "phantglobs.h" 17 #include "pathnames.h" 18 19 #undef bool 20 #include <curses.h> 21 22 static long allocvoid(void); 23 static void battleplayer(long); 24 static void myturn(void); 25 static void tampered(int, double, double); 26 27 void 28 checkbattle(void) 29 { 30 long foeloc = 0L; /* location in file of person to fight */ 31 32 Users = 0; 33 fseek(Playersfp, 0L, SEEK_SET); 34 35 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 36 if (Other.p_status != S_OFF 37 && Other.p_status != S_NOTUSED 38 && Other.p_status != S_HUNGUP 39 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR)) 40 /* player is on and not a cloaked valar */ 41 { 42 ++Users; 43 44 if (Player.p_x == Other.p_x 45 && Player.p_y == Other.p_y 46 /* same coordinates */ 47 && foeloc != Fileloc 48 /* not self */ 49 && Player.p_status == S_PLAYING 50 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE) 51 /* both are playing */ 52 && Other.p_specialtype != SC_VALAR 53 && Player.p_specialtype != SC_VALAR) 54 /* neither is valar */ 55 { 56 battleplayer(foeloc); 57 return; 58 } 59 } 60 foeloc += SZ_PLAYERSTRUCT; 61 } 62 } 63 64 static void 65 battleplayer(long foeplace) 66 { 67 double dtemp; /* for temporary calculations */ 68 double oldhits = 0.0; /* previous damage inflicted by foe */ 69 int loop; /* for timing out */ 70 int ch; /* input */ 71 short oldtampered; /* old value of foe's p_tampered */ 72 73 Lines = 8; 74 Luckout = FALSE; 75 mvaddstr(4, 0, "Preparing for battle!\n"); 76 refresh(); 77 78 #ifdef SYS5 79 flushinp(); 80 #endif 81 82 /* set up variables, file, etc. */ 83 Player.p_status = S_INBATTLE; 84 Shield = Player.p_energy; 85 86 /* if p_tampered is not 0, someone else may try to change it (king, 87 * etc.) */ 88 Player.p_tampered = oldtampered = 1; 89 Player.p_1scratch = 0.0; 90 Player.p_istat = I_OFF; 91 92 readrecord(&Other, foeplace); 93 if (fabs(Player.p_level - Other.p_level) > 20.0) 94 /* see if players are greatly mismatched */ 95 { 96 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level); 97 if (dtemp < -0.5) 98 /* foe outweighs this one */ 99 Player.p_speed *= 2.0; 100 } 101 writerecord(&Player, Fileloc); /* write out all our info */ 102 103 if (Player.p_blindness) 104 Enemyname = "someone"; 105 else 106 Enemyname = Other.p_name; 107 108 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level); 109 refresh(); 110 111 for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop) 112 /* wait for foe to respond */ 113 { 114 readrecord(&Other, foeplace); 115 sleep(1); 116 } 117 118 if (Other.p_status != S_INBATTLE) 119 /* foe did not respond */ 120 { 121 mvprintw(5, 0, "%s is not responding.\n", Enemyname); 122 goto LEAVE; 123 } 124 /* else, we are ready to battle */ 125 126 move(4, 0); 127 clrtoeol(); 128 129 /* 130 * determine who is first master 131 * if neither player is faster, check level 132 * if neither level is greater, battle is not allowed 133 * (this should never happen, but we have to handle it) 134 */ 135 if (Player.p_speed > Other.p_speed) 136 Foestrikes = FALSE; 137 else 138 if (Other.p_speed > Player.p_speed) 139 Foestrikes = TRUE; 140 else 141 if (Player.p_level > Other.p_level) 142 Foestrikes = FALSE; 143 else 144 if (Other.p_level > Player.p_level) 145 Foestrikes = TRUE; 146 else 147 /* no one is faster */ 148 { 149 printw("You can't fight %s yet.", Enemyname); 150 goto LEAVE; 151 } 152 153 for (;;) { 154 displaystats(); 155 readmessage(); 156 mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */ 157 158 if (!Foestrikes) 159 /* take action against foe */ 160 myturn(); 161 else 162 /* wait for foe to take action */ 163 { 164 mvaddstr(4, 0, "Waiting...\n"); 165 clrtoeol(); 166 refresh(); 167 168 for (loop = 0; loop < 20; ++loop) 169 /* wait for foe to act */ 170 { 171 readrecord(&Other, foeplace); 172 if (Other.p_1scratch != oldhits) 173 /* p_1scratch changes to indicate 174 * action */ 175 break; 176 else 177 /* wait and try again */ 178 { 179 sleep(1); 180 addch('.'); 181 refresh(); 182 } 183 } 184 185 if (Other.p_1scratch == oldhits) { 186 /* timeout */ 187 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? "); 188 ch = getanswer("NY", FALSE); 189 move(22, 0); 190 clrtobot(); 191 if (ch == 'Y') 192 continue; 193 else 194 break; 195 } else 196 /* foe took action */ 197 { 198 switch (Other.p_istat) { 199 case I_RAN: /* foe ran away */ 200 mvprintw(Lines++, 0, "%s ran away!", Enemyname); 201 break; 202 203 case I_STUCK: /* foe tried to run, but 204 * couldn't */ 205 mvprintw(Lines++, 0, "%s tried to run away.", Enemyname); 206 break; 207 208 case I_BLEWIT: /* foe tried to luckout, but 209 * didn't */ 210 mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname); 211 break; 212 213 default: 214 dtemp = Other.p_1scratch - oldhits; 215 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp); 216 Shield -= dtemp; 217 break; 218 } 219 220 oldhits = Other.p_1scratch; /* keep track of old 221 * hits */ 222 223 if (Other.p_tampered != oldtampered) 224 /* p_tampered changes to relinquish 225 * turn */ 226 { 227 oldtampered = Other.p_tampered; 228 Foestrikes = FALSE; 229 } 230 } 231 } 232 233 /* decide what happens next */ 234 refresh(); 235 if (Lines > LINES - 2) { 236 more(Lines); 237 move(Lines = 8, 0); 238 clrtobot(); 239 } 240 if (Other.p_istat == I_KILLED || Shield < 0.0) 241 /* we died */ 242 { 243 Shield = -2.0; /* insure this value is negative */ 244 break; 245 } 246 if (Player.p_istat == I_KILLED) 247 /* we killed foe; award treasre */ 248 { 249 mvprintw(Lines++, 0, "You killed %s!", Enemyname); 250 Player.p_experience += Other.p_experience; 251 Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0; 252 Player.p_amulets += Other.p_amulets; 253 Player.p_charms += Other.p_charms; 254 collecttaxes(Other.p_gold, Other.p_gems); 255 Player.p_sword = MAX(Player.p_sword, Other.p_sword); 256 Player.p_shield = MAX(Player.p_shield, Other.p_shield); 257 Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver); 258 if (Other.p_virgin && !Player.p_virgin) { 259 mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? "); 260 if ((ch = getanswer("YN", FALSE)) == 'Y') 261 Player.p_virgin = TRUE; 262 else { 263 ++Player.p_sin; 264 Player.p_experience += 8000.0; 265 } 266 } 267 sleep(3); /* give other person time to die */ 268 break; 269 } else 270 if (Player.p_istat == I_RAN || Other.p_istat == I_RAN) 271 /* either player ran away */ 272 break; 273 } 274 275 LEAVE: 276 /* clean up things and leave */ 277 writerecord(&Player, Fileloc); /* update a final time */ 278 altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */ 279 Player.p_energy = Shield; /* set energy to actual value */ 280 Player.p_tampered = T_OFF; /* clear p_tampered */ 281 282 more(Lines); /* pause */ 283 284 move(4, 0); 285 clrtobot(); /* clear bottom area of screen */ 286 287 if (Player.p_energy < 0.0) 288 /* we are dead */ 289 death("Interterminal battle"); 290 } 291 292 static void 293 myturn(void) 294 { 295 double dtemp; /* for temporary calculations */ 296 int ch; /* input */ 297 298 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast "); 299 if (Luckout) 300 clrtoeol(); 301 else 302 addstr("4:Luckout "); 303 304 ch = inputoption(); 305 move(Lines = 8, 0); 306 clrtobot(); 307 308 switch (ch) { 309 default: /* fight */ 310 dtemp = ROLL(2.0, Player.p_might); 311 HIT: 312 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp); 313 Player.p_sin += 0.5; 314 Player.p_1scratch += dtemp; 315 Player.p_istat = I_OFF; 316 break; 317 318 case '2': /* run away */ 319 Player.p_1scratch -= 1.0; /* change this to indicate 320 * action */ 321 if (drandom() > 0.25) { 322 mvaddstr(Lines++, 0, "You got away!"); 323 Player.p_istat = I_RAN; 324 } else { 325 mvprintw(Lines++, 0, "%s is still after you!", Enemyname); 326 Player.p_istat = I_STUCK; 327 } 328 break; 329 330 case '3': /* power blast */ 331 dtemp = MIN(Player.p_mana, Player.p_level * 5.0); 332 Player.p_mana -= dtemp; 333 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0; 334 mvprintw(Lines++, 0, "You blasted %s !", Enemyname); 335 goto HIT; 336 337 case '4': /* luckout */ 338 if (Luckout || drandom() > 0.1) { 339 if (Luckout) 340 mvaddstr(Lines++, 0, "You already tried that!"); 341 else { 342 mvaddstr(Lines++, 0, "Not this time . . ."); 343 Luckout = TRUE; 344 } 345 346 Player.p_1scratch -= 1.0; 347 Player.p_istat = I_BLEWIT; 348 } else { 349 mvaddstr(Lines++, 0, "You just lucked out!"); 350 Player.p_1scratch = Other.p_energy * 1.1; 351 } 352 break; 353 } 354 355 refresh(); 356 Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */ 357 358 if (Player.p_1scratch > Other.p_energy) 359 Player.p_istat = I_KILLED; 360 else 361 if (drandom() * Player.p_speed < drandom() * Other.p_speed) 362 /* relinquish control */ 363 { 364 ++Player.p_tampered; 365 Foestrikes = TRUE; 366 } 367 writerecord(&Player, Fileloc); /* let foe know what we did */ 368 } 369 370 void 371 checktampered(void) 372 { 373 long loc = 0L; /* location in energy void file */ 374 375 /* first check for energy voids */ 376 fseek(Energyvoidfp, 0L, SEEK_SET); 377 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 378 if (Enrgyvoid.ev_active 379 && Enrgyvoid.ev_x == Player.p_x 380 && Enrgyvoid.ev_y == Player.p_y) 381 /* sitting on one */ 382 { 383 if (loc > 0L) 384 /* not the holy grail; inactivate energy void */ 385 { 386 Enrgyvoid.ev_active = FALSE; 387 writevoid(&Enrgyvoid, loc); 388 tampered(T_NRGVOID, 0.0, 0.0); 389 } else 390 if (Player.p_status != S_CLOAKED) 391 /* holy grail */ 392 tampered(T_GRAIL, 0.0, 0.0); 393 break; 394 } else 395 loc += SZ_VOIDSTRUCT; 396 397 /* now check for other things */ 398 readrecord(&Other, Fileloc); 399 if (Other.p_tampered != T_OFF) 400 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch); 401 } 402 403 static void 404 tampered(int what, double arg1, double arg2) 405 { 406 long loc; /* location in file of other players */ 407 408 Changed = TRUE; 409 move(4, 0); 410 411 Player.p_tampered = T_OFF; /* no longer tampered with */ 412 413 switch (what) { 414 case T_NRGVOID: 415 addstr("You've hit an energy void !\n"); 416 Player.p_mana /= 3.0; 417 Player.p_energy /= 2.0; 418 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1; 419 altercoordinates(0.0, 0.0, A_NEAR); 420 break; 421 422 case T_TRANSPORT: 423 addstr("The king transported you ! "); 424 if (Player.p_charms > 0) { 425 addstr("But your charm saved you. . .\n"); 426 --Player.p_charms; 427 } else { 428 altercoordinates(0.0, 0.0, A_FAR); 429 addch('\n'); 430 } 431 break; 432 433 case T_BESTOW: 434 printw("The king has bestowed %.0f gold pieces on you !\n", arg1); 435 Player.p_gold += arg1; 436 break; 437 438 case T_CURSED: 439 addstr("You've been cursed ! "); 440 if (Player.p_blessing) { 441 addstr("But your blessing saved you. . .\n"); 442 Player.p_blessing = FALSE; 443 } else { 444 addch('\n'); 445 Player.p_poison += 2.0; 446 Player.p_energy = 10.0; 447 Player.p_maxenergy *= 0.95; 448 Player.p_status = S_PLAYING; /* no longer cloaked */ 449 } 450 break; 451 452 case T_VAPORIZED: 453 addstr("You have been vaporized!\n"); 454 more(7); 455 death("Vaporization"); 456 break; 457 458 case T_MONSTER: 459 addstr("The Valar zapped you with a monster!\n"); 460 more(7); 461 encounter((int) arg1); 462 return; 463 464 case T_BLESSED: 465 addstr("The Valar has blessed you!\n"); 466 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield; 467 Player.p_mana += 500.0; 468 Player.p_strength += 0.5; 469 Player.p_brains += 0.5; 470 Player.p_magiclvl += 0.5; 471 Player.p_poison = MIN(0.5, Player.p_poison); 472 break; 473 474 case T_RELOCATE: 475 addstr("You've been relocated. . .\n"); 476 altercoordinates(arg1, arg2, A_FORCED); 477 break; 478 479 case T_HEAL: 480 addstr("You've been healed!\n"); 481 Player.p_poison -= 0.25; 482 Player.p_energy = Player.p_maxenergy + Player.p_shield; 483 break; 484 485 case T_EXVALAR: 486 addstr("You are no longer Valar!\n"); 487 Player.p_specialtype = SC_COUNCIL; 488 break; 489 490 case T_GRAIL: 491 addstr("You have found The Holy Grail!!\n"); 492 if (Player.p_specialtype < SC_COUNCIL) 493 /* must be council of wise to behold grail */ 494 { 495 addstr("However, you are not experienced enough to behold it.\n"); 496 Player.p_sin *= Player.p_sin; 497 Player.p_mana += 1000; 498 } else 499 if (Player.p_specialtype == SC_VALAR 500 || Player.p_specialtype == SC_EXVALAR) { 501 addstr("You have made it to the position of Valar once already.\n"); 502 addstr("The Grail is of no more use to you now.\n"); 503 } else { 504 addstr("It is now time to see if you are worthy to behold it. . .\n"); 505 refresh(); 506 sleep(4); 507 508 if (drandom() / 2.0 < Player.p_sin) { 509 addstr("You have failed!\n"); 510 Player.p_strength = 511 Player.p_mana = 512 Player.p_energy = 513 Player.p_maxenergy = 514 Player.p_magiclvl = 515 Player.p_brains = 516 Player.p_experience = 517 Player.p_quickness = 1.0; 518 519 altercoordinates(1.0, 1.0, A_FORCED); 520 Player.p_level = 0.0; 521 } else { 522 addstr("You made to position of Valar!\n"); 523 Player.p_specialtype = SC_VALAR; 524 Player.p_lives = 5; 525 fseek(Playersfp, 0L, SEEK_SET); 526 loc = 0L; 527 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 528 /* search for existing valar */ 529 if (Other.p_specialtype == SC_VALAR 530 && Other.p_status != S_NOTUSED) 531 /* found old valar */ 532 { 533 Other.p_tampered = T_EXVALAR; 534 writerecord(&Other, loc); 535 break; 536 } else 537 loc += SZ_PLAYERSTRUCT; 538 } 539 } 540 541 /* move grail to new location */ 542 Enrgyvoid.ev_active = TRUE; 543 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6); 544 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6); 545 writevoid(&Enrgyvoid, 0L); 546 break; 547 } 548 refresh(); 549 sleep(2); 550 } 551 552 void 553 userlist(phbool ingameflag) 554 { 555 int numusers = 0; /* number of users on file */ 556 557 if (ingameflag && Player.p_blindness) { 558 mvaddstr(8, 0, "You cannot see anyone.\n"); 559 return; 560 } 561 fseek(Playersfp, 0L, SEEK_SET); 562 mvaddstr(8, 0, 563 "Name X Y Lvl Type Login Status\n"); 564 565 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 566 if (Other.p_status == S_NOTUSED 567 /* record is unused */ 568 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED)) 569 /* cloaked valar */ 570 { 571 if (!Wizard) 572 /* wizard can see everything on file */ 573 continue; 574 } 575 ++numusers; 576 577 if (ingameflag && 578 /* must be playing for the rest of these conditions */ 579 (Player.p_specialtype >= SC_KING 580 /* kings and higher can see others */ 581 || Other.p_specialtype >= SC_KING 582 /* kings and higher can be seen by others */ 583 || Circle >= CIRCLE(Other.p_x, Other.p_y) 584 /* those nearer the origin can be seen */ 585 || Player.p_palantir) 586 /* palantir enables one to see others */ 587 && (Other.p_status != S_CLOAKED 588 || (Player.p_specialtype == SC_VALAR && Player.p_palantir)) 589 /* not cloaked; valar can see through cloak with a palantir */ 590 && Other.p_specialtype != SC_VALAR) 591 /* not a valar */ 592 /* coordinates should be printed */ 593 printw("%-20s %8.0f %8.0f ", 594 Other.p_name, Other.p_x, Other.p_y); 595 else 596 /* cannot see player's coordinates */ 597 printw("%-20s %19.19s ", 598 Other.p_name, descrlocation(&Other, TRUE)); 599 600 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE), 601 Other.p_login, descrstatus(&Other)); 602 603 if ((numusers % (LINES - 10)) == 0) { 604 more(LINES - 1); 605 move(9, 0); 606 clrtobot(); 607 } 608 } 609 610 printw("Total players on file = %d\n", numusers); 611 refresh(); 612 } 613 614 void 615 throneroom(void) 616 { 617 FILE *fp; /* to clear energy voids */ 618 long loc = 0L; /* location of old king in player file */ 619 620 if (Player.p_specialtype < SC_KING) 621 /* not already king -- assumes crown */ 622 { 623 fseek(Playersfp, 0L, SEEK_SET); 624 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 625 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) 626 /* found old king */ 627 { 628 if (Other.p_status != S_OFF) 629 /* old king is playing */ 630 { 631 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n"); 632 altercoordinates(0.0, 0.0, A_NEAR); 633 move(6, 0); 634 return; 635 } else 636 /* old king is not playing - remove 637 * him/her */ 638 { 639 Other.p_specialtype = SC_NONE; 640 if (Other.p_crowns) 641 --Other.p_crowns; 642 writerecord(&Other, loc); 643 break; 644 } 645 } else 646 loc += SZ_PLAYERSTRUCT; 647 648 /* make player new king */ 649 Changed = TRUE; 650 Player.p_specialtype = SC_KING; 651 mvaddstr(4, 0, "You have become king!\n"); 652 653 /* let everyone else know */ 654 fp = fopen(_PATH_MESS, "w"); 655 fprintf(fp, "All hail the new king!"); 656 fclose(fp); 657 658 /* clear all energy voids; retain location of holy grail */ 659 fseek(Energyvoidfp, 0L, SEEK_SET); 660 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 661 fp = fopen(_PATH_VOID, "w"); 662 fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp); 663 fclose(fp); 664 } 665 mvaddstr(6, 0, "0:Decree "); 666 } 667 668 void 669 dotampered(void) 670 { 671 short tamper; /* value for tampering with other players */ 672 const char *option; /* pointer to option description */ 673 double temp1 = 0.0, temp2 = 0.0; /* other tampering values */ 674 int ch; /* input */ 675 long loc; /* location in energy void file */ 676 FILE *fp; /* for opening gold file */ 677 678 move(6, 0); 679 clrtoeol(); 680 if (Player.p_specialtype < SC_COUNCIL && !Wizard) 681 /* king options */ 682 { 683 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes "); 684 685 ch = getanswer(" ", TRUE); 686 move(6, 0); 687 clrtoeol(); 688 move(4, 0); 689 switch (ch) { 690 case '1': /* transport someone */ 691 tamper = T_TRANSPORT; 692 option = "transport"; 693 break; 694 695 case '2': /* curse another */ 696 tamper = T_CURSED; 697 option = "curse"; 698 break; 699 700 case '3': /* create energy void */ 701 if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT) 702 /* can only have 20 void active at once */ 703 mvaddstr(5, 0, "Sorry, void creation limit reached.\n"); 704 else { 705 addstr("Enter the X Y coordinates of void ? "); 706 getstring(Databuf, SZ_DATABUF); 707 sscanf(Databuf, "%lf %lf", &temp1, &temp2); 708 Enrgyvoid.ev_x = floor(temp1); 709 Enrgyvoid.ev_y = floor(temp2); 710 Enrgyvoid.ev_active = TRUE; 711 writevoid(&Enrgyvoid, loc); 712 mvaddstr(5, 0, "It is done.\n"); 713 } 714 return; 715 716 case '4': /* bestow gold to subject */ 717 tamper = T_BESTOW; 718 addstr("How much gold to bestow ? "); 719 temp1 = infloat(); 720 if (temp1 > Player.p_gold || temp1 < 0) { 721 mvaddstr(5, 0, "You don't have that !\n"); 722 return; 723 } 724 /* adjust gold after we are sure it will be given to 725 * someone */ 726 option = "give gold to"; 727 break; 728 729 case '5': /* collect accumulated taxes */ 730 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) 731 /* collect taxes */ 732 { 733 fread((char *) &temp1, sizeof(double), 1, fp); 734 fseek(fp, 0L, SEEK_SET); 735 /* clear out value */ 736 temp2 = 0.0; 737 fwrite((char *) &temp2, sizeof(double), 1, fp); 738 fclose(fp); 739 } 740 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1); 741 Player.p_gold += floor(temp1); 742 return; 743 744 default: 745 return; 746 } 747 /* end of king options */ 748 } else 749 /* council of wise, valar, wizard options */ 750 { 751 addstr("1:Heal "); 752 if (Player.p_palantir || Wizard) 753 addstr("2:Seek Grail "); 754 if (Player.p_specialtype == SC_VALAR || Wizard) 755 addstr("3:Throw Monster 4:Relocate 5:Bless "); 756 if (Wizard) 757 addstr("6:Vaporize "); 758 759 ch = getanswer(" ", TRUE); 760 if (!Wizard) { 761 if (ch > '2' && Player.p_specialtype != SC_VALAR) { 762 ILLCMD(); 763 return; 764 } 765 if (Player.p_mana < MM_INTERVENE) { 766 mvaddstr(5, 0, "No mana left.\n"); 767 return; 768 } else 769 Player.p_mana -= MM_INTERVENE; 770 } 771 switch (ch) { 772 case '1': /* heal another */ 773 tamper = T_HEAL; 774 option = "heal"; 775 break; 776 777 case '2': /* seek grail */ 778 if (Player.p_palantir) 779 /* need a palantir to seek */ 780 { 781 fseek(Energyvoidfp, 0L, SEEK_SET); 782 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 783 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y); 784 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */ 785 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1); 786 } else 787 /* no palantir */ 788 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n"); 789 return; 790 791 case '3': /* lob monster at someone */ 792 mvaddstr(4, 0, "Which monster [0-99] ? "); 793 temp1 = infloat(); 794 temp1 = MAX(0.0, MIN(99.0, temp1)); 795 tamper = T_MONSTER; 796 option = "throw a monster at"; 797 break; 798 799 case '4': /* move another player */ 800 mvaddstr(4, 0, "New X Y coordinates ? "); 801 getstring(Databuf, SZ_DATABUF); 802 sscanf(Databuf, "%lf %lf", &temp1, &temp2); 803 tamper = T_RELOCATE; 804 option = "relocate"; 805 break; 806 807 case '5': /* bless a player */ 808 tamper = T_BLESSED; 809 option = "bless"; 810 break; 811 812 case '6': /* kill off a player */ 813 if (Wizard) { 814 tamper = T_VAPORIZED; 815 option = "vaporize"; 816 break; 817 } else 818 return; 819 820 default: 821 return; 822 } 823 824 /* adjust age after we are sure intervention will be done */ 825 /* end of valar, etc. options */ 826 } 827 828 for (;;) 829 /* prompt for player to affect */ 830 { 831 mvprintw(4, 0, "Who do you want to %s ? ", option); 832 getstring(Databuf, SZ_DATABUF); 833 truncstring(Databuf); 834 835 if (Databuf[0] == '\0') 836 userlist(TRUE); 837 else 838 break; 839 } 840 841 if (strcmp(Player.p_name, Databuf) != 0) 842 /* name other than self */ 843 { 844 if ((loc = findname(Databuf, &Other)) >= 0L) { 845 if (Other.p_tampered != T_OFF) { 846 mvaddstr(5, 0, "That person has something pending already.\n"); 847 return; 848 } else { 849 if (tamper == T_RELOCATE 850 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y) 851 && !Wizard) 852 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n"); 853 else { 854 if (tamper == T_BESTOW) 855 Player.p_gold -= floor(temp1); 856 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER || 857 tamper == T_RELOCATE || tamper == T_BLESSED)) 858 Player.p_age += N_AGE; /* age penalty */ 859 Other.p_tampered = tamper; 860 Other.p_1scratch = floor(temp1); 861 Other.p_2scratch = floor(temp2); 862 writerecord(&Other, loc); 863 mvaddstr(5, 0, "It is done.\n"); 864 } 865 return; 866 } 867 } else 868 /* player not found */ 869 mvaddstr(5, 0, "There is no one by that name.\n"); 870 } else 871 /* self */ 872 mvaddstr(5, 0, "You may not do it to yourself!\n"); 873 } 874 875 void 876 writevoid(struct energyvoid *vp, long loc) 877 { 878 879 fseek(Energyvoidfp, loc, SEEK_SET); 880 fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp); 881 fflush(Energyvoidfp); 882 fseek(Energyvoidfp, 0L, SEEK_SET); 883 } 884 885 static long 886 allocvoid(void) 887 { 888 long loc = 0L; /* location of new energy void */ 889 890 fseek(Energyvoidfp, 0L, SEEK_SET); 891 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 892 if (Enrgyvoid.ev_active) 893 loc += SZ_VOIDSTRUCT; 894 else 895 break; 896 897 return (loc); 898 } 899