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