1 /* $OpenBSD: interplayer.c,v 1.4 2000/06/29 07:39:44 pjanzen Exp $ */ 2 /* $NetBSD: interplayer.c,v 1.2 1995/03/24 03:58:47 cgd Exp $ */ 3 4 /* 5 * interplayer.c - player to player routines for Phantasia 6 */ 7 8 #include "include.h" 9 10 /************************************************************************ 11 / 12 / FUNCTION NAME: checkbattle() 13 / 14 / FUNCTION: check to see if current player should battle another 15 / 16 / AUTHOR: E. A. Estes, 12/4/85 17 / 18 / ARGUMENTS: none 19 / 20 / RETURN VALUE: none 21 / 22 / MODULES CALLED: battleplayer(), fread(), fseek() 23 / 24 / GLOBAL INPUTS: Other, Users, Player, Fileloc, *Playersfp 25 / 26 / GLOBAL OUTPUTS: Users 27 / 28 / DESCRIPTION: 29 / Seach player file for a foe at the same coordinates as the 30 / current player. 31 / Also update user count. 32 / 33 *************************************************************************/ 34 35 void 36 checkbattle() 37 { 38 long foeloc = 0L; /* location in file of person to fight */ 39 40 Users = 0; 41 fseek(Playersfp, 0L, SEEK_SET); 42 43 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 44 if (Other.p_status != S_OFF 45 && Other.p_status != S_NOTUSED 46 && Other.p_status != S_HUNGUP 47 && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR)) 48 /* player is on and not a cloaked valar */ 49 { 50 ++Users; 51 52 if (Player.p_x == Other.p_x 53 && Player.p_y == Other.p_y 54 /* same coordinates */ 55 && foeloc != Fileloc 56 /* not self */ 57 && Player.p_status == S_PLAYING 58 && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE) 59 /* both are playing */ 60 && Other.p_specialtype != SC_VALAR 61 && Player.p_specialtype != SC_VALAR) 62 /* neither is valar */ 63 { 64 battleplayer(foeloc); 65 return; 66 } 67 } 68 foeloc += SZ_PLAYERSTRUCT; 69 } 70 } 71 /**/ 72 /************************************************************************ 73 / 74 / FUNCTION NAME: battleplayer() 75 / 76 / FUNCTION: inter-terminal battle with another player 77 / 78 / AUTHOR: E. A. Estes, 2/15/86 79 / 80 / ARGUMENTS: 81 / long foeplace - location in player file of person to battle 82 / 83 / RETURN VALUE: none 84 / 85 / MODULES CALLED: readrecord(), readmessage(), writerecord(), collecttaxes(), 86 / displaystats(), fabs(), more(), death(), sleep(), wmove(), waddch(), printw(), 87 / myturn(), altercoordinates(), waddstr(), wrefresh(), mvprintw(), 88 / getanswer(), wclrtoeol(), wclrtobot() 89 / 90 / GLOBAL INPUTS: Foestrikes, LINES, Lines, Other, Shield, Player, *stdscr, 91 / Fileloc, *Enemyname 92 / 93 / GLOBAL OUTPUTS: Foestrikes, Lines, Shield, Player, Luckout, *Enemyname 94 / 95 / DESCRIPTION: 96 / Inter-terminal battle is a very fragile and slightly klugy thing. 97 / At any time, one player is master and the other is slave. 98 / We pick who is master first by speed and level. After that, 99 / the slave waits for the master to relinquish its turn, and 100 / the slave becomes master, and so on. 101 / 102 / The items in the player structure which control the handshake are: 103 / p_tampered: 104 / master increments this to relinquish control 105 / p_istat: 106 / master sets this to specify particular action 107 / p_1scratch: 108 / set to total damage inflicted so far; changes to indicate action 109 / 110 *************************************************************************/ 111 112 void 113 battleplayer(foeplace) 114 long foeplace; 115 { 116 double dtemp; /* for temporary calculations */ 117 double oldhits = 0.0; /* previous damage inflicted by foe */ 118 int loop; /* for timing out */ 119 int ch; /* input */ 120 short oldtampered; /* old value of foe's p_tampered */ 121 122 Lines = 8; 123 Luckout = FALSE; 124 mvaddstr(4, 0, "Preparing for battle!\n"); 125 refresh(); 126 127 #ifdef SYS5 128 flushinp(); 129 #endif 130 131 /* set up variables, file, etc. */ 132 Player.p_status = S_INBATTLE; 133 Shield = Player.p_energy; 134 135 /* if p_tampered is not 0, someone else may try to change it (king, 136 * etc.) */ 137 Player.p_tampered = oldtampered = 1; 138 Player.p_1scratch = 0.0; 139 Player.p_istat = I_OFF; 140 141 readrecord(&Other, foeplace); 142 if (fabs(Player.p_level - Other.p_level) > 20.0) 143 /* see if players are greatly mismatched */ 144 { 145 dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level); 146 if (dtemp < -0.5) 147 /* foe outweighs this one */ 148 Player.p_speed *= 2.0; 149 } 150 writerecord(&Player, Fileloc); /* write out all our info */ 151 152 if (Player.p_blindness) 153 Enemyname = "someone"; 154 else 155 Enemyname = Other.p_name; 156 157 mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level); 158 refresh(); 159 160 for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop) 161 /* wait for foe to respond */ 162 { 163 readrecord(&Other, foeplace); 164 sleep(1); 165 } 166 167 if (Other.p_status != S_INBATTLE) 168 /* foe did not respond */ 169 { 170 mvprintw(5, 0, "%s is not responding.\n", Enemyname); 171 goto LEAVE; 172 } 173 /* else, we are ready to battle */ 174 175 move(4, 0); 176 clrtoeol(); 177 178 /* 179 * determine who is first master 180 * if neither player is faster, check level 181 * if neither level is greater, battle is not allowed 182 * (this should never happen, but we have to handle it) 183 */ 184 if (Player.p_speed > Other.p_speed) 185 Foestrikes = FALSE; 186 else if (Other.p_speed > Player.p_speed) 187 Foestrikes = TRUE; 188 else if (Player.p_level > Other.p_level) 189 Foestrikes = FALSE; 190 else if (Other.p_level > Player.p_level) 191 Foestrikes = TRUE; 192 else { 193 /* no one is faster */ 194 printw("You can't fight %s yet.", Enemyname); 195 goto LEAVE; 196 } 197 198 for (;;) { 199 displaystats(); 200 readmessage(); 201 mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */ 202 203 if (!Foestrikes) 204 /* take action against foe */ 205 myturn(); 206 else 207 /* wait for foe to take action */ 208 { 209 mvaddstr(4, 0, "Waiting...\n"); 210 clrtoeol(); 211 refresh(); 212 213 for (loop = 0; loop < 20; ++loop) 214 /* wait for foe to act */ 215 { 216 readrecord(&Other, foeplace); 217 if (Other.p_1scratch != oldhits) 218 /* p_1scratch changes to indicate 219 * action */ 220 break; 221 else 222 /* wait and try again */ 223 { 224 sleep(1); 225 addch('.'); 226 refresh(); 227 } 228 } 229 230 if (Other.p_1scratch == oldhits) { 231 /* timeout */ 232 mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? "); 233 ch = getanswer("NY", FALSE); 234 move(22, 0); 235 clrtobot(); 236 if (ch == 'Y') 237 continue; 238 else 239 break; 240 } else 241 /* foe took action */ 242 { 243 switch (Other.p_istat) { 244 case I_RAN: /* foe ran away */ 245 mvprintw(Lines++, 0, "%s ran away!", Enemyname); 246 break; 247 248 case I_STUCK: /* foe tried to run, but 249 * couldn't */ 250 mvprintw(Lines++, 0, "%s tried to run away.", Enemyname); 251 break; 252 253 case I_BLEWIT: /* foe tried to luckout, but 254 * didn't */ 255 mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname); 256 break; 257 258 default: 259 dtemp = Other.p_1scratch - oldhits; 260 mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp); 261 Shield -= dtemp; 262 break; 263 } 264 265 oldhits = Other.p_1scratch; /* keep track of old 266 * hits */ 267 268 if (Other.p_tampered != oldtampered) 269 /* p_tampered changes to relinquish 270 * turn */ 271 { 272 oldtampered = Other.p_tampered; 273 Foestrikes = FALSE; 274 } 275 } 276 } 277 278 /* decide what happens next */ 279 refresh(); 280 if (Lines > LINES - 2) { 281 more(Lines); 282 move(Lines = 8, 0); 283 clrtobot(); 284 } 285 if (Other.p_istat == I_KILLED || Shield < 0.0) 286 /* we died */ 287 { 288 Shield = -2.0; /* insure this value is negative */ 289 break; 290 } 291 if (Player.p_istat == I_KILLED) 292 /* we killed foe; award treasre */ 293 { 294 mvprintw(Lines++, 0, "You killed %s!", Enemyname); 295 Player.p_experience += Other.p_experience; 296 Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0; 297 Player.p_amulets += Other.p_amulets; 298 Player.p_charms += Other.p_charms; 299 collecttaxes(Other.p_gold, Other.p_gems); 300 Player.p_sword = MAX(Player.p_sword, Other.p_sword); 301 Player.p_shield = MAX(Player.p_shield, Other.p_shield); 302 Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver); 303 if (Other.p_virgin && !Player.p_virgin) { 304 mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? "); 305 if ((ch = getanswer("YN", FALSE)) == 'Y') 306 Player.p_virgin = TRUE; 307 else { 308 ++Player.p_sin; 309 Player.p_experience += 8000.0; 310 } 311 } 312 sleep(3); /* give other person time to die */ 313 break; 314 } else 315 if (Player.p_istat == I_RAN || Other.p_istat == I_RAN) 316 /* either player ran away */ 317 break; 318 } 319 320 LEAVE: 321 /* clean up things and leave */ 322 writerecord(&Player, Fileloc); /* update a final time */ 323 altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */ 324 Player.p_energy = Shield; /* set energy to actual value */ 325 Player.p_tampered = T_OFF; /* clear p_tampered */ 326 327 more(Lines); /* pause */ 328 329 move(4, 0); 330 clrtobot(); /* clear bottom area of screen */ 331 332 if (Player.p_energy < 0.0) 333 /* we are dead */ 334 death("Interterminal battle"); 335 } 336 /**/ 337 /************************************************************************ 338 / 339 / FUNCTION NAME: myturn() 340 / 341 / FUNCTION: process players action against foe in battle 342 / 343 / AUTHOR: E. A. Estes, 2/7/86 344 / 345 / ARGUMENTS: none 346 / 347 / RETURN VALUE: none 348 / 349 / MODULES CALLED: writerecord(), inputoption(), floor(), wmove(), drandom(), 350 / waddstr(), wrefresh(), mvprintw(), wclrtoeol(), wclrtobot() 351 / 352 / GLOBAL INPUTS: Lines, Other, Player, *stdscr, Fileloc, Luckout, 353 / *Enemyname 354 / 355 / GLOBAL OUTPUTS: Foestrikes, Lines, Player, Luckout 356 / 357 / DESCRIPTION: 358 / Take action action against foe, and decide who is master 359 / for next iteration. 360 / 361 *************************************************************************/ 362 363 void 364 myturn() 365 { 366 double dtemp; /* for temporary calculations */ 367 int ch; /* input */ 368 369 mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast "); 370 if (Luckout) 371 clrtoeol(); 372 else 373 addstr("4:Luckout "); 374 375 ch = inputoption(); 376 move(Lines = 8, 0); 377 clrtobot(); 378 379 switch (ch) { 380 default: /* fight */ 381 dtemp = ROLL(2.0, Player.p_might); 382 HIT: 383 mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp); 384 Player.p_sin += 0.5; 385 Player.p_1scratch += dtemp; 386 Player.p_istat = I_OFF; 387 break; 388 389 case '2': /* run away */ 390 Player.p_1scratch -= 1.0; /* change this to indicate 391 * action */ 392 if (drandom() > 0.25) { 393 mvaddstr(Lines++, 0, "You got away!"); 394 Player.p_istat = I_RAN; 395 } else { 396 mvprintw(Lines++, 0, "%s is still after you!", Enemyname); 397 Player.p_istat = I_STUCK; 398 } 399 break; 400 401 case '3': /* power blast */ 402 dtemp = MIN(Player.p_mana, Player.p_level * 5.0); 403 Player.p_mana -= dtemp; 404 dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0; 405 mvprintw(Lines++, 0, "You blasted %s !", Enemyname); 406 goto HIT; 407 408 case '4': /* luckout */ 409 if (Luckout || drandom() > 0.1) { 410 if (Luckout) 411 mvaddstr(Lines++, 0, "You already tried that!"); 412 else { 413 mvaddstr(Lines++, 0, "Not this time . . ."); 414 Luckout = TRUE; 415 } 416 417 Player.p_1scratch -= 1.0; 418 Player.p_istat = I_BLEWIT; 419 } else { 420 mvaddstr(Lines++, 0, "You just lucked out!"); 421 Player.p_1scratch = Other.p_energy * 1.1; 422 } 423 break; 424 } 425 426 refresh(); 427 Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */ 428 429 if (Player.p_1scratch > Other.p_energy) 430 Player.p_istat = I_KILLED; 431 else 432 if (drandom() * Player.p_speed < drandom() * Other.p_speed) 433 /* relinquish control */ 434 { 435 ++Player.p_tampered; 436 Foestrikes = TRUE; 437 } 438 writerecord(&Player, Fileloc); /* let foe know what we did */ 439 } 440 /**/ 441 /************************************************************************ 442 / 443 / FUNCTION NAME: checktampered() 444 / 445 / FUNCTION: check if current player has been tampered with 446 / 447 / AUTHOR: E. A. Estes, 12/4/85 448 / 449 / ARGUMENTS: none 450 / 451 / RETURN VALUE: none 452 / 453 / MODULES CALLED: readrecord(), fread(), fseek(), tampered(), writevoid() 454 / 455 / GLOBAL INPUTS: *Energyvoidfp, Other, Player, Fileloc, Enrgyvoid 456 / 457 / GLOBAL OUTPUTS: Enrgyvoid 458 / 459 / DESCRIPTION: 460 / Check for energy voids, holy grail, and tampering by other 461 / players. 462 / 463 *************************************************************************/ 464 465 void 466 checktampered() 467 { 468 long loc = 0L; /* location in energy void file */ 469 470 /* first check for energy voids */ 471 fseek(Energyvoidfp, 0L, SEEK_SET); 472 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 473 if (Enrgyvoid.ev_active 474 && Enrgyvoid.ev_x == Player.p_x 475 && Enrgyvoid.ev_y == Player.p_y) 476 /* sitting on one */ 477 { 478 if (loc > 0L) 479 /* not the holy grail; inactivate energy void */ 480 { 481 Enrgyvoid.ev_active = FALSE; 482 writevoid(&Enrgyvoid, loc); 483 tampered(T_NRGVOID, 0.0, 0.0); 484 } else 485 if (Player.p_status != S_CLOAKED) 486 /* holy grail */ 487 tampered(T_GRAIL, 0.0, 0.0); 488 break; 489 } else 490 loc += SZ_VOIDSTRUCT; 491 492 /* now check for other things */ 493 readrecord(&Other, Fileloc); 494 if (Other.p_tampered != T_OFF) 495 tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch); 496 } 497 /**/ 498 /************************************************************************ 499 / 500 / FUNCTION NAME: tampered() 501 / 502 / FUNCTION: take care of tampering by other players 503 / 504 / AUTHOR: E. A. Estes, 12/4/85 505 / 506 / ARGUMENTS: 507 / int what - what type of tampering 508 / double arg1, arg2 - rest of tampering info 509 / 510 / RETURN VALUE: none 511 / 512 / MODULES CALLED: writerecord(), more(), fread(), death(), fseek(), sleep(), 513 / floor(), wmove(), waddch(), drandom(), printw(), altercoordinates(), 514 / waddstr(), wrefresh(), encounter(), writevoid() 515 / 516 / GLOBAL INPUTS: Other, Player, *stdscr, Enrgyvoid, *Playersfp 517 / 518 / GLOBAL OUTPUTS: Other, Player, Changed, Enrgyvoid 519 / 520 / DESCRIPTION: 521 / Take care of energy voids, holy grail, decree and intervention 522 / action on current player. 523 / 524 *************************************************************************/ 525 526 void 527 tampered(what, arg1, arg2) 528 int what; 529 double arg1; 530 double arg2; 531 { 532 long loc; /* location in file of other players */ 533 534 Changed = TRUE; 535 move(4, 0); 536 537 Player.p_tampered = T_OFF; /* no longer tampered with */ 538 539 switch (what) { 540 case T_NRGVOID: 541 addstr("You've hit an energy void !\n"); 542 Player.p_mana /= 3.0; 543 Player.p_energy /= 2.0; 544 Player.p_gold = floor(Player.p_gold / 1.25) + 0.1; 545 altercoordinates(0.0, 0.0, A_NEAR); 546 break; 547 548 case T_TRANSPORT: 549 addstr("The king transported you ! "); 550 if (Player.p_charms > 0) { 551 addstr("But your charm saved you. . .\n"); 552 --Player.p_charms; 553 } else { 554 altercoordinates(0.0, 0.0, A_FAR); 555 addch('\n'); 556 } 557 break; 558 559 case T_BESTOW: 560 printw("The king has bestowed %.0f gold pieces on you !\n", arg1); 561 Player.p_gold += arg1; 562 break; 563 564 case T_CURSED: 565 addstr("You've been cursed ! "); 566 if (Player.p_blessing) { 567 addstr("But your blessing saved you. . .\n"); 568 Player.p_blessing = FALSE; 569 } else { 570 addch('\n'); 571 Player.p_poison += 2.0; 572 Player.p_energy = 10.0; 573 Player.p_maxenergy *= 0.95; 574 Player.p_status = S_PLAYING; /* no longer cloaked */ 575 } 576 break; 577 578 case T_VAPORIZED: 579 addstr("You have been vaporized!\n"); 580 more(7); 581 death("Vaporization"); 582 break; 583 584 case T_MONSTER: 585 addstr("The Valar zapped you with a monster!\n"); 586 more(7); 587 encounter((int) arg1); 588 return; 589 590 case T_BLESSED: 591 addstr("The Valar has blessed you!\n"); 592 Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield; 593 Player.p_mana += 500.0; 594 Player.p_strength += 0.5; 595 Player.p_brains += 0.5; 596 Player.p_magiclvl += 0.5; 597 Player.p_poison = MIN(0.5, Player.p_poison); 598 break; 599 600 case T_RELOCATE: 601 addstr("You've been relocated. . .\n"); 602 altercoordinates(arg1, arg2, A_FORCED); 603 break; 604 605 case T_HEAL: 606 addstr("You've been healed!\n"); 607 Player.p_poison -= 0.25; 608 Player.p_energy = Player.p_maxenergy + Player.p_shield; 609 break; 610 611 case T_EXVALAR: 612 addstr("You are no longer Valar!\n"); 613 Player.p_specialtype = SC_COUNCIL; 614 break; 615 616 case T_GRAIL: 617 addstr("You have found The Holy Grail!!\n"); 618 if (Player.p_specialtype < SC_COUNCIL) 619 /* must be council of wise to behold grail */ 620 { 621 addstr("However, you are not experienced enough to behold it.\n"); 622 Player.p_sin *= Player.p_sin; 623 Player.p_mana += 1000; 624 } else 625 if (Player.p_specialtype == SC_VALAR 626 || Player.p_specialtype == SC_EXVALAR) { 627 addstr("You have made it to the position of Valar once already.\n"); 628 addstr("The Grail is of no more use to you now.\n"); 629 } else { 630 addstr("It is now time to see if you are worthy to behold it. . .\n"); 631 refresh(); 632 sleep(4); 633 634 if (drandom() / 2.0 < Player.p_sin) { 635 addstr("You have failed!\n"); 636 Player.p_strength = 637 Player.p_mana = 638 Player.p_energy = 639 Player.p_maxenergy = 640 Player.p_magiclvl = 641 Player.p_brains = 642 Player.p_experience = 643 Player.p_quickness = 1.0; 644 645 altercoordinates(1.0, 1.0, A_FORCED); 646 Player.p_level = 0.0; 647 } else { 648 addstr("You made to position of Valar!\n"); 649 Player.p_specialtype = SC_VALAR; 650 Player.p_lives = 5; 651 fseek(Playersfp, 0L, SEEK_SET); 652 loc = 0L; 653 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 654 /* search for existing valar */ 655 if (Other.p_specialtype == SC_VALAR 656 && Other.p_status != S_NOTUSED) 657 /* found old valar */ 658 { 659 Other.p_tampered = T_EXVALAR; 660 writerecord(&Other, loc); 661 break; 662 } else 663 loc += SZ_PLAYERSTRUCT; 664 } 665 } 666 667 /* move grail to new location */ 668 Enrgyvoid.ev_active = TRUE; 669 Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6); 670 Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6); 671 writevoid(&Enrgyvoid, 0L); 672 break; 673 } 674 refresh(); 675 sleep(2); 676 } 677 /**/ 678 /************************************************************************ 679 / 680 / FUNCTION NAME: userlist() 681 / 682 / FUNCTION: print list of players and locations 683 / 684 / AUTHOR: E. A. Estes, 2/28/86 685 / 686 / ARGUMENTS: 687 / bool ingameflag - set if called while playing 688 / 689 / RETURN VALUE: none 690 / 691 / MODULES CALLED: descrstatus(), descrlocation(), more(), fread(), fseek(), 692 / floor(), wmove(), printw(), waddstr(), distance(), wrefresh(), 693 / descrtype(), wclrtobot() 694 / 695 / GLOBAL INPUTS: LINES, Other, Circle, Wizard, Player, *stdscr, *Playersfp 696 / 697 / GLOBAL OUTPUTS: none 698 / 699 / DESCRIPTION: 700 / We can only see the coordinate of those closer to the origin 701 / from us. 702 / Kings and council of the wise can see and can be seen by everyone. 703 / Palantirs are good for seeing everyone; and the valar can use 704 / one to see through a 'cloak' spell. 705 / The valar has no coordinates, and is completely invisible if 706 / cloaked. 707 / 708 *************************************************************************/ 709 710 void 711 userlist(ingameflag) 712 bool ingameflag; 713 { 714 int numusers = 0; /* number of users on file */ 715 716 if (ingameflag && Player.p_blindness) { 717 mvaddstr(8, 0, "You cannot see anyone.\n"); 718 return; 719 } 720 fseek(Playersfp, 0L, SEEK_SET); 721 mvaddstr(8, 0, 722 "Name X Y Lvl Type Login Status\n"); 723 724 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 725 if (Other.p_status == S_NOTUSED 726 /* record is unused */ 727 || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED)) 728 /* cloaked valar */ 729 { 730 if (!Wizard) 731 /* wizard can see everything on file */ 732 continue; 733 } 734 ++numusers; 735 736 if (ingameflag && 737 /* must be playing for the rest of these conditions */ 738 (Player.p_specialtype >= SC_KING 739 /* kings and higher can see others */ 740 || Other.p_specialtype >= SC_KING 741 /* kings and higher can be seen by others */ 742 || Circle >= CIRCLE(Other.p_x, Other.p_y) 743 /* those nearer the origin can be seen */ 744 || Player.p_palantir) 745 /* palantir enables one to see others */ 746 && (Other.p_status != S_CLOAKED 747 || (Player.p_specialtype == SC_VALAR && Player.p_palantir)) 748 /* not cloaked; valar can see through cloak with a palantir */ 749 && Other.p_specialtype != SC_VALAR) 750 /* not a valar */ 751 /* coordinates should be printed */ 752 printw("%-20s %8.0f %8.0f ", 753 Other.p_name, Other.p_x, Other.p_y); 754 else 755 /* cannot see player's coordinates */ 756 printw("%-20s %19.19s ", 757 Other.p_name, descrlocation(&Other, TRUE)); 758 759 printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE), 760 Other.p_login, descrstatus(&Other)); 761 762 if ((numusers % (LINES - 10)) == 0) { 763 more(LINES - 1); 764 move(9, 0); 765 clrtobot(); 766 } 767 } 768 769 printw("Total players on file = %d\n", numusers); 770 refresh(); 771 } 772 /**/ 773 /************************************************************************ 774 / 775 / FUNCTION NAME: throneroom() 776 / 777 / FUNCTION: king stuff upon entering throne 778 / 779 / AUTHOR: E. A. Estes, 12/16/85 780 / 781 / ARGUMENTS: none 782 / 783 / RETURN VALUE: none 784 / 785 / MODULES CALLED: writerecord(), fread(), fseek(), fopen(), wmove(), fclose(), 786 / fwrite(), altercoordinates(), waddstr(), fprintf() 787 / 788 / GLOBAL INPUTS: *Energyvoidfp, Other, Player, *stdscr, 789 / Enrgyvoid, *Playersfp 790 / 791 / GLOBAL OUTPUTS: Other, Player, Changed 792 / 793 / DESCRIPTION: 794 / If player is not already king, make him/her so if the old king 795 / is not playing. 796 / Clear energy voids with new king. 797 / Print 'decree' prompt. 798 / 799 *************************************************************************/ 800 801 void 802 throneroom() 803 { 804 FILE *fp; /* to clear energy voids */ 805 long loc = 0L; /* location of old king in player file */ 806 807 if (Player.p_specialtype < SC_KING) 808 /* not already king -- assumes crown */ 809 { 810 fseek(Playersfp, 0L, SEEK_SET); 811 while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 812 if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) 813 /* found old king */ 814 { 815 if (Other.p_status != S_OFF) 816 /* old king is playing */ 817 { 818 mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n"); 819 altercoordinates(0.0, 0.0, A_NEAR); 820 move(6, 0); 821 return; 822 } else 823 /* old king is not playing - remove 824 * him/her */ 825 { 826 Other.p_specialtype = SC_NONE; 827 if (Other.p_crowns) 828 --Other.p_crowns; 829 writerecord(&Other, loc); 830 break; 831 } 832 } else 833 loc += SZ_PLAYERSTRUCT; 834 835 /* make player new king */ 836 Changed = TRUE; 837 Player.p_specialtype = SC_KING; 838 mvaddstr(4, 0, "You have become king!\n"); 839 840 /* let everyone else know */ 841 fp = fopen(_PATH_MESS, "w"); 842 fprintf(fp, "All hail the new king!"); 843 fclose(fp); 844 845 /* clear all energy voids; retain location of holy grail */ 846 fseek(Energyvoidfp, 0L, SEEK_SET); 847 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 848 fp = fopen(_PATH_VOID, "w"); 849 fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp); 850 fclose(fp); 851 } 852 mvaddstr(6, 0, "0:Decree "); 853 } 854 /**/ 855 /************************************************************************ 856 / 857 / FUNCTION NAME: dotampered() 858 / 859 / FUNCTION: king and valar special options 860 / 861 / AUTHOR: E. A. Estes, 2/28/86 862 / 863 / ARGUMENTS: none 864 / 865 / RETURN VALUE: none 866 / 867 / MODULES CALLED: writerecord(), truncstring(), fread(), fseek(), fopen(), 868 / floor(), wmove(), drandom(), fclose(), fwrite(), sscanf(), strcmp(), 869 / infloat(), waddstr(), findname(), distance(), userlist(), mvprintw(), 870 / allocvoid(), getanswer(), getstring(), wclrtoeol(), writevoid() 871 / 872 / GLOBAL INPUTS: *Energyvoidfp, Other, Illcmd[], Wizard, Player, *stdscr, 873 / Databuf[], Enrgyvoid 874 / 875 / GLOBAL OUTPUTS: Other, Player, Enrgyvoid 876 / 877 / DESCRIPTION: 878 / Tamper with other players. Handle king/valar specific options. 879 / 880 *************************************************************************/ 881 882 void 883 dotampered() 884 { 885 short tamper; /* value for tampering with other players */ 886 char *option; /* pointer to option description */ 887 double temp1 = 0.0, temp2 = 0.0; /* other tampering values */ 888 int ch; /* input */ 889 long loc; /* location in energy void file */ 890 FILE *fp; /* for opening gold file */ 891 892 move(6, 0); 893 clrtoeol(); 894 if (Player.p_specialtype < SC_COUNCIL && !Wizard) 895 /* king options */ 896 { 897 addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes "); 898 899 ch = getanswer(" ", TRUE); 900 move(6, 0); 901 clrtoeol(); 902 move(4, 0); 903 switch (ch) { 904 case '1': /* transport someone */ 905 tamper = T_TRANSPORT; 906 option = "transport"; 907 break; 908 909 case '2': /* curse another */ 910 tamper = T_CURSED; 911 option = "curse"; 912 break; 913 914 case '3': /* create energy void */ 915 if ((loc = allocvoid()) > 20L * SZ_VOIDSTRUCT) 916 /* can only have 20 void active at once */ 917 mvaddstr(5, 0, "Sorry, void creation limit reached.\n"); 918 else { 919 addstr("Enter the X Y coordinates of void ? "); 920 getstring(Databuf, SZ_DATABUF); 921 sscanf(Databuf, "%lf %lf", &temp1, &temp2); 922 Enrgyvoid.ev_x = floor(temp1); 923 Enrgyvoid.ev_y = floor(temp2); 924 Enrgyvoid.ev_active = TRUE; 925 writevoid(&Enrgyvoid, loc); 926 mvaddstr(5, 0, "It is done.\n"); 927 } 928 return; 929 930 case '4': /* bestow gold to subject */ 931 tamper = T_BESTOW; 932 addstr("How much gold to bestow ? "); 933 temp1 = infloat(); 934 if (temp1 > Player.p_gold || temp1 < 0) { 935 mvaddstr(5, 0, "You don't have that !\n"); 936 return; 937 } 938 /* adjust gold after we are sure it will be given to 939 * someone */ 940 option = "give gold to"; 941 break; 942 943 case '5': /* collect accumulated taxes */ 944 if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) 945 /* collect taxes */ 946 { 947 fread((char *) &temp1, sizeof(double), 1, fp); 948 fseek(fp, 0L, SEEK_SET); 949 /* clear out value */ 950 temp2 = 0.0; 951 fwrite((char *) &temp2, sizeof(double), 1, fp); 952 fclose(fp); 953 } 954 mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1); 955 Player.p_gold += floor(temp1); 956 return; 957 958 default: 959 return; 960 } 961 /* end of king options */ 962 } else 963 /* council of wise, valar, wizard options */ 964 { 965 addstr("1:Heal "); 966 if (Player.p_palantir || Wizard) 967 addstr("2:Seek Grail "); 968 if (Player.p_specialtype == SC_VALAR || Wizard) 969 addstr("3:Throw Monster 4:Relocate 5:Bless "); 970 if (Wizard) 971 addstr("6:Vaporize "); 972 973 ch = getanswer(" ", TRUE); 974 if (!Wizard) { 975 if (ch > '2' && Player.p_specialtype != SC_VALAR) { 976 ILLCMD(); 977 return; 978 } 979 if (Player.p_mana < MM_INTERVENE) { 980 mvaddstr(5, 0, "No mana left.\n"); 981 return; 982 } else 983 Player.p_mana -= MM_INTERVENE; 984 } 985 switch (ch) { 986 case '1': /* heal another */ 987 tamper = T_HEAL; 988 option = "heal"; 989 break; 990 991 case '2': /* seek grail */ 992 if (Player.p_palantir) 993 /* need a palantir to seek */ 994 { 995 fseek(Energyvoidfp, 0L, SEEK_SET); 996 fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 997 temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y); 998 temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */ 999 mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1); 1000 } else 1001 /* no palantir */ 1002 mvaddstr(5, 0, "You need a palantir to seek the Grail.\n"); 1003 return; 1004 1005 case '3': /* lob monster at someone */ 1006 mvaddstr(4, 0, "Which monster [0-99] ? "); 1007 temp1 = infloat(); 1008 temp1 = MAX(0.0, MIN(99.0, temp1)); 1009 tamper = T_MONSTER; 1010 option = "throw a monster at"; 1011 break; 1012 1013 case '4': /* move another player */ 1014 mvaddstr(4, 0, "New X Y coordinates ? "); 1015 getstring(Databuf, SZ_DATABUF); 1016 sscanf(Databuf, "%lf %lf", &temp1, &temp2); 1017 tamper = T_RELOCATE; 1018 option = "relocate"; 1019 break; 1020 1021 case '5': /* bless a player */ 1022 tamper = T_BLESSED; 1023 option = "bless"; 1024 break; 1025 1026 case '6': /* kill off a player */ 1027 if (Wizard) { 1028 tamper = T_VAPORIZED; 1029 option = "vaporize"; 1030 break; 1031 } else 1032 return; 1033 1034 default: 1035 return; 1036 } 1037 1038 /* adjust age after we are sure intervention will be done */ 1039 /* end of valar, etc. options */ 1040 } 1041 1042 for (;;) 1043 /* prompt for player to affect */ 1044 { 1045 mvprintw(4, 0, "Who do you want to %s ? ", option); 1046 getstring(Databuf, SZ_DATABUF); 1047 truncstring(Databuf); 1048 1049 if (Databuf[0] == '\0') 1050 userlist(TRUE); 1051 else 1052 break; 1053 } 1054 1055 if (strcmp(Player.p_name, Databuf) != 0) 1056 /* name other than self */ 1057 { 1058 if ((loc = findname(Databuf, &Other)) >= 0L) { 1059 if (Other.p_tampered != T_OFF) { 1060 mvaddstr(5, 0, "That person has something pending already.\n"); 1061 return; 1062 } else { 1063 if (tamper == T_RELOCATE 1064 && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y) 1065 && !Wizard) 1066 mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n"); 1067 else { 1068 if (tamper == T_BESTOW) 1069 Player.p_gold -= floor(temp1); 1070 if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER || 1071 tamper == T_RELOCATE || tamper == T_BLESSED)) 1072 Player.p_age += N_AGE; /* age penalty */ 1073 Other.p_tampered = tamper; 1074 Other.p_1scratch = floor(temp1); 1075 Other.p_2scratch = floor(temp2); 1076 writerecord(&Other, loc); 1077 mvaddstr(5, 0, "It is done.\n"); 1078 } 1079 return; 1080 } 1081 } else 1082 /* player not found */ 1083 mvaddstr(5, 0, "There is no one by that name.\n"); 1084 } else 1085 /* self */ 1086 mvaddstr(5, 0, "You may not do it to yourself!\n"); 1087 } 1088 /**/ 1089 /************************************************************************ 1090 / 1091 / FUNCTION NAME: writevoid() 1092 / 1093 / FUNCTION: update energy void entry in energy void file 1094 / 1095 / AUTHOR: E. A. Estes, 12/4/85 1096 / 1097 / ARGUMENTS: 1098 / struct energyvoid *vp - pointer to structure to write to file 1099 / long loc - location in file to update 1100 / 1101 / RETURN VALUE: none 1102 / 1103 / MODULES CALLED: fseek(), fwrite(), fflush() 1104 / 1105 / GLOBAL INPUTS: *Energyvoidfp 1106 / 1107 / GLOBAL OUTPUTS: none 1108 / 1109 / DESCRIPTION: 1110 / Write out energy void structure at specified location. 1111 / 1112 *************************************************************************/ 1113 1114 void 1115 writevoid(vp, loc) 1116 struct energyvoid *vp; 1117 long loc; 1118 { 1119 1120 fseek(Energyvoidfp, loc, SEEK_SET); 1121 fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp); 1122 fflush(Energyvoidfp); 1123 fseek(Energyvoidfp, 0L, SEEK_SET); 1124 } 1125 /**/ 1126 /************************************************************************ 1127 / 1128 / FUNCTION NAME: allocvoid() 1129 / 1130 / FUNCTION: allocate space for a new energy void 1131 / 1132 / AUTHOR: E. A. Estes, 12/4/85 1133 / 1134 / ARGUMENTS: none 1135 / 1136 / RETURN VALUE: location of new energy void space 1137 / 1138 / MODULES CALLED: fread(), fseek() 1139 / 1140 / GLOBAL INPUTS: *Energyvoidfp, Enrgyvoid 1141 / 1142 / GLOBAL OUTPUTS: none 1143 / 1144 / DESCRIPTION: 1145 / Search energy void file for an inactive entry and return its 1146 / location. 1147 / If no inactive ones are found, return one more than last location. 1148 / 1149 *************************************************************************/ 1150 1151 long 1152 allocvoid() 1153 { 1154 long loc = 0L; /* location of new energy void */ 1155 1156 fseek(Energyvoidfp, 0L, SEEK_SET); 1157 while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 1158 if (Enrgyvoid.ev_active) 1159 loc += SZ_VOIDSTRUCT; 1160 else 1161 break; 1162 1163 return (loc); 1164 } 1165