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