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