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