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