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