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