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