1 1.12 dholland /* $NetBSD: interplayer.c,v 1.12 2009/08/31 08:27:16 dholland Exp $ */ 2 1.2 cgd 3 1.1 jtc /* 4 1.1 jtc * interplayer.c - player to player routines for Phantasia 5 1.1 jtc */ 6 1.1 jtc 7 1.12 dholland #include <math.h> 8 1.12 dholland #include <setjmp.h> 9 1.12 dholland #include <stdio.h> 10 1.12 dholland #include <string.h> 11 1.12 dholland #include <unistd.h> 12 1.12 dholland 13 1.12 dholland #include "macros.h" 14 1.12 dholland #include "phantdefs.h" 15 1.12 dholland #include "phantstruct.h" 16 1.12 dholland #include "phantglobs.h" 17 1.12 dholland #include "pathnames.h" 18 1.12 dholland 19 1.8 he #undef bool 20 1.7 ross #include <curses.h> 21 1.1 jtc 22 1.11 dholland static long allocvoid(void); 23 1.11 dholland static void battleplayer(long); 24 1.11 dholland static void myturn(void); 25 1.11 dholland static void tampered(int, double, double); 26 1.11 dholland 27 1.3 lukem void 28 1.10 dholland checkbattle(void) 29 1.1 jtc { 30 1.3 lukem long foeloc = 0L; /* location in file of person to fight */ 31 1.1 jtc 32 1.3 lukem Users = 0; 33 1.5 jsm fseek(Playersfp, 0L, SEEK_SET); 34 1.1 jtc 35 1.3 lukem while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 36 1.3 lukem if (Other.p_status != S_OFF 37 1.3 lukem && Other.p_status != S_NOTUSED 38 1.3 lukem && Other.p_status != S_HUNGUP 39 1.3 lukem && (Other.p_status != S_CLOAKED || Other.p_specialtype != SC_VALAR)) 40 1.3 lukem /* player is on and not a cloaked valar */ 41 1.3 lukem { 42 1.3 lukem ++Users; 43 1.3 lukem 44 1.3 lukem if (Player.p_x == Other.p_x 45 1.3 lukem && Player.p_y == Other.p_y 46 1.3 lukem /* same coordinates */ 47 1.3 lukem && foeloc != Fileloc 48 1.3 lukem /* not self */ 49 1.3 lukem && Player.p_status == S_PLAYING 50 1.3 lukem && (Other.p_status == S_PLAYING || Other.p_status == S_INBATTLE) 51 1.3 lukem /* both are playing */ 52 1.3 lukem && Other.p_specialtype != SC_VALAR 53 1.3 lukem && Player.p_specialtype != SC_VALAR) 54 1.3 lukem /* neither is valar */ 55 1.3 lukem { 56 1.3 lukem battleplayer(foeloc); 57 1.3 lukem return; 58 1.3 lukem } 59 1.1 jtc } 60 1.3 lukem foeloc += SZ_PLAYERSTRUCT; 61 1.1 jtc } 62 1.1 jtc } 63 1.1 jtc 64 1.11 dholland static void 65 1.10 dholland battleplayer(long foeplace) 66 1.1 jtc { 67 1.3 lukem double dtemp; /* for temporary calculations */ 68 1.3 lukem double oldhits = 0.0; /* previous damage inflicted by foe */ 69 1.3 lukem int loop; /* for timing out */ 70 1.3 lukem int ch; /* input */ 71 1.3 lukem short oldtampered; /* old value of foe's p_tampered */ 72 1.3 lukem 73 1.3 lukem Lines = 8; 74 1.3 lukem Luckout = FALSE; 75 1.3 lukem mvaddstr(4, 0, "Preparing for battle!\n"); 76 1.3 lukem refresh(); 77 1.1 jtc 78 1.1 jtc #ifdef SYS5 79 1.3 lukem flushinp(); 80 1.1 jtc #endif 81 1.1 jtc 82 1.3 lukem /* set up variables, file, etc. */ 83 1.3 lukem Player.p_status = S_INBATTLE; 84 1.3 lukem Shield = Player.p_energy; 85 1.3 lukem 86 1.3 lukem /* if p_tampered is not 0, someone else may try to change it (king, 87 1.3 lukem * etc.) */ 88 1.3 lukem Player.p_tampered = oldtampered = 1; 89 1.3 lukem Player.p_1scratch = 0.0; 90 1.3 lukem Player.p_istat = I_OFF; 91 1.3 lukem 92 1.3 lukem readrecord(&Other, foeplace); 93 1.3 lukem if (fabs(Player.p_level - Other.p_level) > 20.0) 94 1.3 lukem /* see if players are greatly mismatched */ 95 1.1 jtc { 96 1.3 lukem dtemp = (Player.p_level - Other.p_level) / MAX(Player.p_level, Other.p_level); 97 1.3 lukem if (dtemp < -0.5) 98 1.3 lukem /* foe outweighs this one */ 99 1.3 lukem Player.p_speed *= 2.0; 100 1.1 jtc } 101 1.3 lukem writerecord(&Player, Fileloc); /* write out all our info */ 102 1.1 jtc 103 1.3 lukem if (Player.p_blindness) 104 1.3 lukem Enemyname = "someone"; 105 1.3 lukem else 106 1.3 lukem Enemyname = Other.p_name; 107 1.1 jtc 108 1.3 lukem mvprintw(6, 0, "You have encountered %s Level: %.0f\n", Enemyname, Other.p_level); 109 1.3 lukem refresh(); 110 1.1 jtc 111 1.3 lukem for (loop = 0; Other.p_status != S_INBATTLE && loop < 30; ++loop) 112 1.3 lukem /* wait for foe to respond */ 113 1.1 jtc { 114 1.3 lukem readrecord(&Other, foeplace); 115 1.3 lukem sleep(1); 116 1.1 jtc } 117 1.1 jtc 118 1.3 lukem if (Other.p_status != S_INBATTLE) 119 1.3 lukem /* foe did not respond */ 120 1.1 jtc { 121 1.3 lukem mvprintw(5, 0, "%s is not responding.\n", Enemyname); 122 1.3 lukem goto LEAVE; 123 1.1 jtc } 124 1.3 lukem /* else, we are ready to battle */ 125 1.1 jtc 126 1.3 lukem move(4, 0); 127 1.3 lukem clrtoeol(); 128 1.1 jtc 129 1.3 lukem /* 130 1.3 lukem * determine who is first master 131 1.3 lukem * if neither player is faster, check level 132 1.3 lukem * if neither level is greater, battle is not allowed 133 1.3 lukem * (this should never happen, but we have to handle it) 134 1.3 lukem */ 135 1.3 lukem if (Player.p_speed > Other.p_speed) 136 1.3 lukem Foestrikes = FALSE; 137 1.1 jtc else 138 1.3 lukem if (Other.p_speed > Player.p_speed) 139 1.3 lukem Foestrikes = TRUE; 140 1.3 lukem else 141 1.3 lukem if (Player.p_level > Other.p_level) 142 1.3 lukem Foestrikes = FALSE; 143 1.3 lukem else 144 1.3 lukem if (Other.p_level > Player.p_level) 145 1.3 lukem Foestrikes = TRUE; 146 1.3 lukem else 147 1.3 lukem /* no one is faster */ 148 1.3 lukem { 149 1.3 lukem printw("You can't fight %s yet.", Enemyname); 150 1.3 lukem goto LEAVE; 151 1.3 lukem } 152 1.3 lukem 153 1.3 lukem for (;;) { 154 1.3 lukem displaystats(); 155 1.3 lukem readmessage(); 156 1.3 lukem mvprintw(1, 26, "%20.0f", Shield); /* overprint energy */ 157 1.3 lukem 158 1.3 lukem if (!Foestrikes) 159 1.3 lukem /* take action against foe */ 160 1.3 lukem myturn(); 161 1.3 lukem else 162 1.3 lukem /* wait for foe to take action */ 163 1.1 jtc { 164 1.3 lukem mvaddstr(4, 0, "Waiting...\n"); 165 1.3 lukem clrtoeol(); 166 1.3 lukem refresh(); 167 1.3 lukem 168 1.3 lukem for (loop = 0; loop < 20; ++loop) 169 1.3 lukem /* wait for foe to act */ 170 1.3 lukem { 171 1.3 lukem readrecord(&Other, foeplace); 172 1.3 lukem if (Other.p_1scratch != oldhits) 173 1.3 lukem /* p_1scratch changes to indicate 174 1.3 lukem * action */ 175 1.3 lukem break; 176 1.3 lukem else 177 1.3 lukem /* wait and try again */ 178 1.3 lukem { 179 1.3 lukem sleep(1); 180 1.3 lukem addch('.'); 181 1.3 lukem refresh(); 182 1.3 lukem } 183 1.3 lukem } 184 1.3 lukem 185 1.3 lukem if (Other.p_1scratch == oldhits) { 186 1.3 lukem /* timeout */ 187 1.3 lukem mvaddstr(22, 0, "Timeout: waiting for response. Do you want to wait ? "); 188 1.3 lukem ch = getanswer("NY", FALSE); 189 1.3 lukem move(22, 0); 190 1.3 lukem clrtobot(); 191 1.3 lukem if (ch == 'Y') 192 1.3 lukem continue; 193 1.3 lukem else 194 1.3 lukem break; 195 1.3 lukem } else 196 1.3 lukem /* foe took action */ 197 1.3 lukem { 198 1.3 lukem switch (Other.p_istat) { 199 1.3 lukem case I_RAN: /* foe ran away */ 200 1.3 lukem mvprintw(Lines++, 0, "%s ran away!", Enemyname); 201 1.3 lukem break; 202 1.3 lukem 203 1.3 lukem case I_STUCK: /* foe tried to run, but 204 1.3 lukem * couldn't */ 205 1.3 lukem mvprintw(Lines++, 0, "%s tried to run away.", Enemyname); 206 1.3 lukem break; 207 1.3 lukem 208 1.3 lukem case I_BLEWIT: /* foe tried to luckout, but 209 1.3 lukem * didn't */ 210 1.3 lukem mvprintw(Lines++, 0, "%s tried to luckout!", Enemyname); 211 1.3 lukem break; 212 1.3 lukem 213 1.3 lukem default: 214 1.3 lukem dtemp = Other.p_1scratch - oldhits; 215 1.3 lukem mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, dtemp); 216 1.3 lukem Shield -= dtemp; 217 1.3 lukem break; 218 1.3 lukem } 219 1.3 lukem 220 1.3 lukem oldhits = Other.p_1scratch; /* keep track of old 221 1.3 lukem * hits */ 222 1.3 lukem 223 1.3 lukem if (Other.p_tampered != oldtampered) 224 1.3 lukem /* p_tampered changes to relinquish 225 1.3 lukem * turn */ 226 1.3 lukem { 227 1.3 lukem oldtampered = Other.p_tampered; 228 1.3 lukem Foestrikes = FALSE; 229 1.3 lukem } 230 1.3 lukem } 231 1.1 jtc } 232 1.1 jtc 233 1.3 lukem /* decide what happens next */ 234 1.3 lukem refresh(); 235 1.3 lukem if (Lines > LINES - 2) { 236 1.3 lukem more(Lines); 237 1.3 lukem move(Lines = 8, 0); 238 1.3 lukem clrtobot(); 239 1.3 lukem } 240 1.3 lukem if (Other.p_istat == I_KILLED || Shield < 0.0) 241 1.3 lukem /* we died */ 242 1.1 jtc { 243 1.3 lukem Shield = -2.0; /* insure this value is negative */ 244 1.3 lukem break; 245 1.1 jtc } 246 1.3 lukem if (Player.p_istat == I_KILLED) 247 1.3 lukem /* we killed foe; award treasre */ 248 1.1 jtc { 249 1.3 lukem mvprintw(Lines++, 0, "You killed %s!", Enemyname); 250 1.3 lukem Player.p_experience += Other.p_experience; 251 1.3 lukem Player.p_crowns += (Player.p_level < 1000.0) ? Other.p_crowns : 0; 252 1.3 lukem Player.p_amulets += Other.p_amulets; 253 1.3 lukem Player.p_charms += Other.p_charms; 254 1.3 lukem collecttaxes(Other.p_gold, Other.p_gems); 255 1.3 lukem Player.p_sword = MAX(Player.p_sword, Other.p_sword); 256 1.3 lukem Player.p_shield = MAX(Player.p_shield, Other.p_shield); 257 1.3 lukem Player.p_quksilver = MAX(Player.p_quksilver, Other.p_quksilver); 258 1.3 lukem if (Other.p_virgin && !Player.p_virgin) { 259 1.3 lukem mvaddstr(Lines++, 0, "You have rescued a virgin. Will you be honorable ? "); 260 1.3 lukem if ((ch = getanswer("YN", FALSE)) == 'Y') 261 1.3 lukem Player.p_virgin = TRUE; 262 1.3 lukem else { 263 1.3 lukem ++Player.p_sin; 264 1.3 lukem Player.p_experience += 8000.0; 265 1.3 lukem } 266 1.3 lukem } 267 1.3 lukem sleep(3); /* give other person time to die */ 268 1.1 jtc break; 269 1.3 lukem } else 270 1.3 lukem if (Player.p_istat == I_RAN || Other.p_istat == I_RAN) 271 1.3 lukem /* either player ran away */ 272 1.3 lukem break; 273 1.3 lukem } 274 1.1 jtc 275 1.3 lukem LEAVE: 276 1.3 lukem /* clean up things and leave */ 277 1.3 lukem writerecord(&Player, Fileloc); /* update a final time */ 278 1.3 lukem altercoordinates(0.0, 0.0, A_NEAR); /* move away from battle site */ 279 1.3 lukem Player.p_energy = Shield; /* set energy to actual value */ 280 1.3 lukem Player.p_tampered = T_OFF; /* clear p_tampered */ 281 1.1 jtc 282 1.3 lukem more(Lines); /* pause */ 283 1.1 jtc 284 1.3 lukem move(4, 0); 285 1.3 lukem clrtobot(); /* clear bottom area of screen */ 286 1.1 jtc 287 1.3 lukem if (Player.p_energy < 0.0) 288 1.3 lukem /* we are dead */ 289 1.3 lukem death("Interterminal battle"); 290 1.1 jtc } 291 1.1 jtc 292 1.11 dholland static void 293 1.10 dholland myturn(void) 294 1.1 jtc { 295 1.3 lukem double dtemp; /* for temporary calculations */ 296 1.3 lukem int ch; /* input */ 297 1.1 jtc 298 1.3 lukem mvaddstr(7, 0, "1:Fight 2:Run Away! 3:Power Blast "); 299 1.3 lukem if (Luckout) 300 1.3 lukem clrtoeol(); 301 1.3 lukem else 302 1.3 lukem addstr("4:Luckout "); 303 1.1 jtc 304 1.3 lukem ch = inputoption(); 305 1.3 lukem move(Lines = 8, 0); 306 1.3 lukem clrtobot(); 307 1.3 lukem 308 1.3 lukem switch (ch) { 309 1.3 lukem default: /* fight */ 310 1.3 lukem dtemp = ROLL(2.0, Player.p_might); 311 1.3 lukem HIT: 312 1.3 lukem mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, dtemp); 313 1.3 lukem Player.p_sin += 0.5; 314 1.3 lukem Player.p_1scratch += dtemp; 315 1.3 lukem Player.p_istat = I_OFF; 316 1.3 lukem break; 317 1.1 jtc 318 1.3 lukem case '2': /* run away */ 319 1.3 lukem Player.p_1scratch -= 1.0; /* change this to indicate 320 1.3 lukem * action */ 321 1.3 lukem if (drandom() > 0.25) { 322 1.3 lukem mvaddstr(Lines++, 0, "You got away!"); 323 1.3 lukem Player.p_istat = I_RAN; 324 1.3 lukem } else { 325 1.3 lukem mvprintw(Lines++, 0, "%s is still after you!", Enemyname); 326 1.3 lukem Player.p_istat = I_STUCK; 327 1.1 jtc } 328 1.3 lukem break; 329 1.3 lukem 330 1.3 lukem case '3': /* power blast */ 331 1.3 lukem dtemp = MIN(Player.p_mana, Player.p_level * 5.0); 332 1.3 lukem Player.p_mana -= dtemp; 333 1.3 lukem dtemp *= (drandom() + 0.5) * Player.p_magiclvl * 0.2 + 2.0; 334 1.3 lukem mvprintw(Lines++, 0, "You blasted %s !", Enemyname); 335 1.3 lukem goto HIT; 336 1.3 lukem 337 1.3 lukem case '4': /* luckout */ 338 1.3 lukem if (Luckout || drandom() > 0.1) { 339 1.3 lukem if (Luckout) 340 1.3 lukem mvaddstr(Lines++, 0, "You already tried that!"); 341 1.3 lukem else { 342 1.3 lukem mvaddstr(Lines++, 0, "Not this time . . ."); 343 1.3 lukem Luckout = TRUE; 344 1.3 lukem } 345 1.3 lukem 346 1.3 lukem Player.p_1scratch -= 1.0; 347 1.3 lukem Player.p_istat = I_BLEWIT; 348 1.3 lukem } else { 349 1.3 lukem mvaddstr(Lines++, 0, "You just lucked out!"); 350 1.3 lukem Player.p_1scratch = Other.p_energy * 1.1; 351 1.1 jtc } 352 1.3 lukem break; 353 1.3 lukem } 354 1.1 jtc 355 1.3 lukem refresh(); 356 1.3 lukem Player.p_1scratch = floor(Player.p_1scratch); /* clean up any mess */ 357 1.1 jtc 358 1.3 lukem if (Player.p_1scratch > Other.p_energy) 359 1.3 lukem Player.p_istat = I_KILLED; 360 1.3 lukem else 361 1.3 lukem if (drandom() * Player.p_speed < drandom() * Other.p_speed) 362 1.3 lukem /* relinquish control */ 363 1.1 jtc { 364 1.3 lukem ++Player.p_tampered; 365 1.3 lukem Foestrikes = TRUE; 366 1.1 jtc } 367 1.3 lukem writerecord(&Player, Fileloc); /* let foe know what we did */ 368 1.1 jtc } 369 1.1 jtc 370 1.3 lukem void 371 1.10 dholland checktampered(void) 372 1.1 jtc { 373 1.3 lukem long loc = 0L; /* location in energy void file */ 374 1.1 jtc 375 1.3 lukem /* first check for energy voids */ 376 1.5 jsm fseek(Energyvoidfp, 0L, SEEK_SET); 377 1.3 lukem while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 378 1.3 lukem if (Enrgyvoid.ev_active 379 1.3 lukem && Enrgyvoid.ev_x == Player.p_x 380 1.3 lukem && Enrgyvoid.ev_y == Player.p_y) 381 1.3 lukem /* sitting on one */ 382 1.3 lukem { 383 1.3 lukem if (loc > 0L) 384 1.3 lukem /* not the holy grail; inactivate energy void */ 385 1.3 lukem { 386 1.3 lukem Enrgyvoid.ev_active = FALSE; 387 1.3 lukem writevoid(&Enrgyvoid, loc); 388 1.3 lukem tampered(T_NRGVOID, 0.0, 0.0); 389 1.3 lukem } else 390 1.3 lukem if (Player.p_status != S_CLOAKED) 391 1.3 lukem /* holy grail */ 392 1.3 lukem tampered(T_GRAIL, 0.0, 0.0); 393 1.3 lukem break; 394 1.3 lukem } else 395 1.3 lukem loc += SZ_VOIDSTRUCT; 396 1.1 jtc 397 1.3 lukem /* now check for other things */ 398 1.3 lukem readrecord(&Other, Fileloc); 399 1.3 lukem if (Other.p_tampered != T_OFF) 400 1.3 lukem tampered(Other.p_tampered, Other.p_1scratch, Other.p_2scratch); 401 1.1 jtc } 402 1.1 jtc 403 1.11 dholland static void 404 1.10 dholland tampered(int what, double arg1, double arg2) 405 1.1 jtc { 406 1.3 lukem long loc; /* location in file of other players */ 407 1.1 jtc 408 1.3 lukem Changed = TRUE; 409 1.3 lukem move(4, 0); 410 1.1 jtc 411 1.3 lukem Player.p_tampered = T_OFF; /* no longer tampered with */ 412 1.1 jtc 413 1.3 lukem switch (what) { 414 1.1 jtc case T_NRGVOID: 415 1.3 lukem addstr("You've hit an energy void !\n"); 416 1.3 lukem Player.p_mana /= 3.0; 417 1.3 lukem Player.p_energy /= 2.0; 418 1.3 lukem Player.p_gold = floor(Player.p_gold / 1.25) + 0.1; 419 1.3 lukem altercoordinates(0.0, 0.0, A_NEAR); 420 1.3 lukem break; 421 1.1 jtc 422 1.1 jtc case T_TRANSPORT: 423 1.3 lukem addstr("The king transported you ! "); 424 1.3 lukem if (Player.p_charms > 0) { 425 1.3 lukem addstr("But your charm saved you. . .\n"); 426 1.3 lukem --Player.p_charms; 427 1.3 lukem } else { 428 1.3 lukem altercoordinates(0.0, 0.0, A_FAR); 429 1.3 lukem addch('\n'); 430 1.1 jtc } 431 1.3 lukem break; 432 1.1 jtc 433 1.1 jtc case T_BESTOW: 434 1.3 lukem printw("The king has bestowed %.0f gold pieces on you !\n", arg1); 435 1.3 lukem Player.p_gold += arg1; 436 1.3 lukem break; 437 1.1 jtc 438 1.1 jtc case T_CURSED: 439 1.3 lukem addstr("You've been cursed ! "); 440 1.3 lukem if (Player.p_blessing) { 441 1.3 lukem addstr("But your blessing saved you. . .\n"); 442 1.3 lukem Player.p_blessing = FALSE; 443 1.3 lukem } else { 444 1.3 lukem addch('\n'); 445 1.3 lukem Player.p_poison += 2.0; 446 1.3 lukem Player.p_energy = 10.0; 447 1.3 lukem Player.p_maxenergy *= 0.95; 448 1.3 lukem Player.p_status = S_PLAYING; /* no longer cloaked */ 449 1.1 jtc } 450 1.3 lukem break; 451 1.1 jtc 452 1.1 jtc case T_VAPORIZED: 453 1.3 lukem addstr("You have been vaporized!\n"); 454 1.3 lukem more(7); 455 1.3 lukem death("Vaporization"); 456 1.3 lukem break; 457 1.1 jtc 458 1.1 jtc case T_MONSTER: 459 1.3 lukem addstr("The Valar zapped you with a monster!\n"); 460 1.3 lukem more(7); 461 1.3 lukem encounter((int) arg1); 462 1.3 lukem return; 463 1.1 jtc 464 1.1 jtc case T_BLESSED: 465 1.3 lukem addstr("The Valar has blessed you!\n"); 466 1.3 lukem Player.p_energy = (Player.p_maxenergy *= 1.05) + Player.p_shield; 467 1.3 lukem Player.p_mana += 500.0; 468 1.3 lukem Player.p_strength += 0.5; 469 1.3 lukem Player.p_brains += 0.5; 470 1.3 lukem Player.p_magiclvl += 0.5; 471 1.3 lukem Player.p_poison = MIN(0.5, Player.p_poison); 472 1.3 lukem break; 473 1.1 jtc 474 1.1 jtc case T_RELOCATE: 475 1.3 lukem addstr("You've been relocated. . .\n"); 476 1.3 lukem altercoordinates(arg1, arg2, A_FORCED); 477 1.3 lukem break; 478 1.1 jtc 479 1.1 jtc case T_HEAL: 480 1.3 lukem addstr("You've been healed!\n"); 481 1.3 lukem Player.p_poison -= 0.25; 482 1.3 lukem Player.p_energy = Player.p_maxenergy + Player.p_shield; 483 1.3 lukem break; 484 1.1 jtc 485 1.1 jtc case T_EXVALAR: 486 1.3 lukem addstr("You are no longer Valar!\n"); 487 1.3 lukem Player.p_specialtype = SC_COUNCIL; 488 1.3 lukem break; 489 1.1 jtc 490 1.1 jtc case T_GRAIL: 491 1.3 lukem addstr("You have found The Holy Grail!!\n"); 492 1.3 lukem if (Player.p_specialtype < SC_COUNCIL) 493 1.3 lukem /* must be council of wise to behold grail */ 494 1.3 lukem { 495 1.3 lukem addstr("However, you are not experienced enough to behold it.\n"); 496 1.3 lukem Player.p_sin *= Player.p_sin; 497 1.3 lukem Player.p_mana += 1000; 498 1.3 lukem } else 499 1.3 lukem if (Player.p_specialtype == SC_VALAR 500 1.3 lukem || Player.p_specialtype == SC_EXVALAR) { 501 1.3 lukem addstr("You have made it to the position of Valar once already.\n"); 502 1.3 lukem addstr("The Grail is of no more use to you now.\n"); 503 1.3 lukem } else { 504 1.3 lukem addstr("It is now time to see if you are worthy to behold it. . .\n"); 505 1.3 lukem refresh(); 506 1.3 lukem sleep(4); 507 1.3 lukem 508 1.3 lukem if (drandom() / 2.0 < Player.p_sin) { 509 1.3 lukem addstr("You have failed!\n"); 510 1.3 lukem Player.p_strength = 511 1.3 lukem Player.p_mana = 512 1.3 lukem Player.p_energy = 513 1.3 lukem Player.p_maxenergy = 514 1.3 lukem Player.p_magiclvl = 515 1.3 lukem Player.p_brains = 516 1.3 lukem Player.p_experience = 517 1.3 lukem Player.p_quickness = 1.0; 518 1.3 lukem 519 1.3 lukem altercoordinates(1.0, 1.0, A_FORCED); 520 1.3 lukem Player.p_level = 0.0; 521 1.3 lukem } else { 522 1.3 lukem addstr("You made to position of Valar!\n"); 523 1.3 lukem Player.p_specialtype = SC_VALAR; 524 1.3 lukem Player.p_lives = 5; 525 1.5 jsm fseek(Playersfp, 0L, SEEK_SET); 526 1.3 lukem loc = 0L; 527 1.3 lukem while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 528 1.3 lukem /* search for existing valar */ 529 1.3 lukem if (Other.p_specialtype == SC_VALAR 530 1.3 lukem && Other.p_status != S_NOTUSED) 531 1.3 lukem /* found old valar */ 532 1.3 lukem { 533 1.3 lukem Other.p_tampered = T_EXVALAR; 534 1.3 lukem writerecord(&Other, loc); 535 1.3 lukem break; 536 1.3 lukem } else 537 1.3 lukem loc += SZ_PLAYERSTRUCT; 538 1.3 lukem } 539 1.3 lukem } 540 1.3 lukem 541 1.3 lukem /* move grail to new location */ 542 1.3 lukem Enrgyvoid.ev_active = TRUE; 543 1.3 lukem Enrgyvoid.ev_x = ROLL(-1.0e6, 2.0e6); 544 1.3 lukem Enrgyvoid.ev_y = ROLL(-1.0e6, 2.0e6); 545 1.3 lukem writevoid(&Enrgyvoid, 0L); 546 1.3 lukem break; 547 1.1 jtc } 548 1.3 lukem refresh(); 549 1.3 lukem sleep(2); 550 1.1 jtc } 551 1.1 jtc 552 1.3 lukem void 553 1.10 dholland userlist(phbool ingameflag) 554 1.1 jtc { 555 1.3 lukem int numusers = 0; /* number of users on file */ 556 1.1 jtc 557 1.3 lukem if (ingameflag && Player.p_blindness) { 558 1.3 lukem mvaddstr(8, 0, "You cannot see anyone.\n"); 559 1.3 lukem return; 560 1.1 jtc } 561 1.5 jsm fseek(Playersfp, 0L, SEEK_SET); 562 1.3 lukem mvaddstr(8, 0, 563 1.3 lukem "Name X Y Lvl Type Login Status\n"); 564 1.1 jtc 565 1.3 lukem while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) { 566 1.3 lukem if (Other.p_status == S_NOTUSED 567 1.3 lukem /* record is unused */ 568 1.3 lukem || (Other.p_specialtype == SC_VALAR && Other.p_status == S_CLOAKED)) 569 1.3 lukem /* cloaked valar */ 570 1.3 lukem { 571 1.3 lukem if (!Wizard) 572 1.3 lukem /* wizard can see everything on file */ 573 1.3 lukem continue; 574 1.3 lukem } 575 1.3 lukem ++numusers; 576 1.1 jtc 577 1.3 lukem if (ingameflag && 578 1.1 jtc /* must be playing for the rest of these conditions */ 579 1.3 lukem (Player.p_specialtype >= SC_KING 580 1.1 jtc /* kings and higher can see others */ 581 1.3 lukem || Other.p_specialtype >= SC_KING 582 1.1 jtc /* kings and higher can be seen by others */ 583 1.3 lukem || Circle >= CIRCLE(Other.p_x, Other.p_y) 584 1.1 jtc /* those nearer the origin can be seen */ 585 1.3 lukem || Player.p_palantir) 586 1.1 jtc /* palantir enables one to see others */ 587 1.3 lukem && (Other.p_status != S_CLOAKED 588 1.3 lukem || (Player.p_specialtype == SC_VALAR && Player.p_palantir)) 589 1.1 jtc /* not cloaked; valar can see through cloak with a palantir */ 590 1.3 lukem && Other.p_specialtype != SC_VALAR) 591 1.3 lukem /* not a valar */ 592 1.3 lukem /* coordinates should be printed */ 593 1.3 lukem printw("%-20s %8.0f %8.0f ", 594 1.3 lukem Other.p_name, Other.p_x, Other.p_y); 595 1.3 lukem else 596 1.3 lukem /* cannot see player's coordinates */ 597 1.3 lukem printw("%-20s %19.19s ", 598 1.3 lukem Other.p_name, descrlocation(&Other, TRUE)); 599 1.3 lukem 600 1.3 lukem printw("%6.0f %s %-9.9s%s\n", Other.p_level, descrtype(&Other, TRUE), 601 1.3 lukem Other.p_login, descrstatus(&Other)); 602 1.3 lukem 603 1.3 lukem if ((numusers % (LINES - 10)) == 0) { 604 1.3 lukem more(LINES - 1); 605 1.3 lukem move(9, 0); 606 1.3 lukem clrtobot(); 607 1.3 lukem } 608 1.1 jtc } 609 1.1 jtc 610 1.3 lukem printw("Total players on file = %d\n", numusers); 611 1.3 lukem refresh(); 612 1.1 jtc } 613 1.1 jtc 614 1.3 lukem void 615 1.10 dholland throneroom(void) 616 1.1 jtc { 617 1.3 lukem FILE *fp; /* to clear energy voids */ 618 1.3 lukem long loc = 0L; /* location of old king in player file */ 619 1.1 jtc 620 1.3 lukem if (Player.p_specialtype < SC_KING) 621 1.3 lukem /* not already king -- assumes crown */ 622 1.1 jtc { 623 1.5 jsm fseek(Playersfp, 0L, SEEK_SET); 624 1.3 lukem while (fread((char *) &Other, SZ_PLAYERSTRUCT, 1, Playersfp) == 1) 625 1.3 lukem if (Other.p_specialtype == SC_KING && Other.p_status != S_NOTUSED) 626 1.3 lukem /* found old king */ 627 1.3 lukem { 628 1.3 lukem if (Other.p_status != S_OFF) 629 1.3 lukem /* old king is playing */ 630 1.3 lukem { 631 1.3 lukem mvaddstr(4, 0, "The king is playing, so you cannot steal his throne\n"); 632 1.3 lukem altercoordinates(0.0, 0.0, A_NEAR); 633 1.3 lukem move(6, 0); 634 1.3 lukem return; 635 1.3 lukem } else 636 1.3 lukem /* old king is not playing - remove 637 1.3 lukem * him/her */ 638 1.3 lukem { 639 1.3 lukem Other.p_specialtype = SC_NONE; 640 1.3 lukem if (Other.p_crowns) 641 1.3 lukem --Other.p_crowns; 642 1.3 lukem writerecord(&Other, loc); 643 1.3 lukem break; 644 1.3 lukem } 645 1.3 lukem } else 646 1.3 lukem loc += SZ_PLAYERSTRUCT; 647 1.3 lukem 648 1.3 lukem /* make player new king */ 649 1.3 lukem Changed = TRUE; 650 1.3 lukem Player.p_specialtype = SC_KING; 651 1.3 lukem mvaddstr(4, 0, "You have become king!\n"); 652 1.3 lukem 653 1.3 lukem /* let everyone else know */ 654 1.3 lukem fp = fopen(_PATH_MESS, "w"); 655 1.3 lukem fprintf(fp, "All hail the new king!"); 656 1.3 lukem fclose(fp); 657 1.3 lukem 658 1.3 lukem /* clear all energy voids; retain location of holy grail */ 659 1.5 jsm fseek(Energyvoidfp, 0L, SEEK_SET); 660 1.3 lukem fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 661 1.3 lukem fp = fopen(_PATH_VOID, "w"); 662 1.3 lukem fwrite((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, fp); 663 1.3 lukem fclose(fp); 664 1.1 jtc } 665 1.3 lukem mvaddstr(6, 0, "0:Decree "); 666 1.1 jtc } 667 1.1 jtc 668 1.3 lukem void 669 1.10 dholland dotampered(void) 670 1.1 jtc { 671 1.3 lukem short tamper; /* value for tampering with other players */ 672 1.4 jsm const char *option; /* pointer to option description */ 673 1.3 lukem double temp1 = 0.0, temp2 = 0.0; /* other tampering values */ 674 1.3 lukem int ch; /* input */ 675 1.3 lukem long loc; /* location in energy void file */ 676 1.3 lukem FILE *fp; /* for opening gold file */ 677 1.1 jtc 678 1.1 jtc move(6, 0); 679 1.1 jtc clrtoeol(); 680 1.3 lukem if (Player.p_specialtype < SC_COUNCIL && !Wizard) 681 1.3 lukem /* king options */ 682 1.3 lukem { 683 1.3 lukem addstr("1:Transport 2:Curse 3:Energy Void 4:Bestow 5:Collect Taxes "); 684 1.1 jtc 685 1.3 lukem ch = getanswer(" ", TRUE); 686 1.3 lukem move(6, 0); 687 1.3 lukem clrtoeol(); 688 1.3 lukem move(4, 0); 689 1.3 lukem switch (ch) { 690 1.3 lukem case '1': /* transport someone */ 691 1.3 lukem tamper = T_TRANSPORT; 692 1.3 lukem option = "transport"; 693 1.3 lukem break; 694 1.1 jtc 695 1.3 lukem case '2': /* curse another */ 696 1.3 lukem tamper = T_CURSED; 697 1.3 lukem option = "curse"; 698 1.3 lukem break; 699 1.1 jtc 700 1.3 lukem case '3': /* create energy void */ 701 1.6 jsm if ((loc = allocvoid()) > 20L * (long)SZ_VOIDSTRUCT) 702 1.3 lukem /* can only have 20 void active at once */ 703 1.3 lukem mvaddstr(5, 0, "Sorry, void creation limit reached.\n"); 704 1.3 lukem else { 705 1.3 lukem addstr("Enter the X Y coordinates of void ? "); 706 1.3 lukem getstring(Databuf, SZ_DATABUF); 707 1.3 lukem sscanf(Databuf, "%lf %lf", &temp1, &temp2); 708 1.3 lukem Enrgyvoid.ev_x = floor(temp1); 709 1.3 lukem Enrgyvoid.ev_y = floor(temp2); 710 1.3 lukem Enrgyvoid.ev_active = TRUE; 711 1.3 lukem writevoid(&Enrgyvoid, loc); 712 1.3 lukem mvaddstr(5, 0, "It is done.\n"); 713 1.3 lukem } 714 1.3 lukem return; 715 1.3 lukem 716 1.3 lukem case '4': /* bestow gold to subject */ 717 1.3 lukem tamper = T_BESTOW; 718 1.3 lukem addstr("How much gold to bestow ? "); 719 1.3 lukem temp1 = infloat(); 720 1.3 lukem if (temp1 > Player.p_gold || temp1 < 0) { 721 1.3 lukem mvaddstr(5, 0, "You don't have that !\n"); 722 1.3 lukem return; 723 1.3 lukem } 724 1.3 lukem /* adjust gold after we are sure it will be given to 725 1.3 lukem * someone */ 726 1.3 lukem option = "give gold to"; 727 1.3 lukem break; 728 1.1 jtc 729 1.3 lukem case '5': /* collect accumulated taxes */ 730 1.3 lukem if ((fp = fopen(_PATH_GOLD, "r+")) != NULL) 731 1.3 lukem /* collect taxes */ 732 1.3 lukem { 733 1.3 lukem fread((char *) &temp1, sizeof(double), 1, fp); 734 1.5 jsm fseek(fp, 0L, SEEK_SET); 735 1.3 lukem /* clear out value */ 736 1.3 lukem temp2 = 0.0; 737 1.3 lukem fwrite((char *) &temp2, sizeof(double), 1, fp); 738 1.3 lukem fclose(fp); 739 1.3 lukem } 740 1.3 lukem mvprintw(4, 0, "You have collected %.0f in gold.\n", temp1); 741 1.3 lukem Player.p_gold += floor(temp1); 742 1.3 lukem return; 743 1.3 lukem 744 1.3 lukem default: 745 1.3 lukem return; 746 1.3 lukem } 747 1.3 lukem /* end of king options */ 748 1.3 lukem } else 749 1.3 lukem /* council of wise, valar, wizard options */ 750 1.3 lukem { 751 1.3 lukem addstr("1:Heal "); 752 1.3 lukem if (Player.p_palantir || Wizard) 753 1.3 lukem addstr("2:Seek Grail "); 754 1.3 lukem if (Player.p_specialtype == SC_VALAR || Wizard) 755 1.3 lukem addstr("3:Throw Monster 4:Relocate 5:Bless "); 756 1.3 lukem if (Wizard) 757 1.3 lukem addstr("6:Vaporize "); 758 1.1 jtc 759 1.3 lukem ch = getanswer(" ", TRUE); 760 1.3 lukem if (!Wizard) { 761 1.3 lukem if (ch > '2' && Player.p_specialtype != SC_VALAR) { 762 1.3 lukem ILLCMD(); 763 1.3 lukem return; 764 1.3 lukem } 765 1.3 lukem if (Player.p_mana < MM_INTERVENE) { 766 1.3 lukem mvaddstr(5, 0, "No mana left.\n"); 767 1.3 lukem return; 768 1.3 lukem } else 769 1.3 lukem Player.p_mana -= MM_INTERVENE; 770 1.3 lukem } 771 1.3 lukem switch (ch) { 772 1.3 lukem case '1': /* heal another */ 773 1.3 lukem tamper = T_HEAL; 774 1.3 lukem option = "heal"; 775 1.3 lukem break; 776 1.1 jtc 777 1.3 lukem case '2': /* seek grail */ 778 1.3 lukem if (Player.p_palantir) 779 1.3 lukem /* need a palantir to seek */ 780 1.3 lukem { 781 1.5 jsm fseek(Energyvoidfp, 0L, SEEK_SET); 782 1.3 lukem fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp); 783 1.3 lukem temp1 = distance(Player.p_x, Enrgyvoid.ev_x, Player.p_y, Enrgyvoid.ev_y); 784 1.3 lukem temp1 += ROLL(-temp1 / 10.0, temp1 / 5.0); /* add some error */ 785 1.3 lukem mvprintw(5, 0, "The palantir says the Grail is about %.0f away.\n", temp1); 786 1.3 lukem } else 787 1.3 lukem /* no palantir */ 788 1.3 lukem mvaddstr(5, 0, "You need a palantir to seek the Grail.\n"); 789 1.3 lukem return; 790 1.3 lukem 791 1.3 lukem case '3': /* lob monster at someone */ 792 1.3 lukem mvaddstr(4, 0, "Which monster [0-99] ? "); 793 1.3 lukem temp1 = infloat(); 794 1.3 lukem temp1 = MAX(0.0, MIN(99.0, temp1)); 795 1.3 lukem tamper = T_MONSTER; 796 1.3 lukem option = "throw a monster at"; 797 1.3 lukem break; 798 1.1 jtc 799 1.3 lukem case '4': /* move another player */ 800 1.3 lukem mvaddstr(4, 0, "New X Y coordinates ? "); 801 1.3 lukem getstring(Databuf, SZ_DATABUF); 802 1.3 lukem sscanf(Databuf, "%lf %lf", &temp1, &temp2); 803 1.3 lukem tamper = T_RELOCATE; 804 1.3 lukem option = "relocate"; 805 1.3 lukem break; 806 1.1 jtc 807 1.3 lukem case '5': /* bless a player */ 808 1.3 lukem tamper = T_BLESSED; 809 1.3 lukem option = "bless"; 810 1.3 lukem break; 811 1.1 jtc 812 1.3 lukem case '6': /* kill off a player */ 813 1.3 lukem if (Wizard) { 814 1.3 lukem tamper = T_VAPORIZED; 815 1.3 lukem option = "vaporize"; 816 1.3 lukem break; 817 1.3 lukem } else 818 1.3 lukem return; 819 1.1 jtc 820 1.3 lukem default: 821 1.3 lukem return; 822 1.3 lukem } 823 1.1 jtc 824 1.3 lukem /* adjust age after we are sure intervention will be done */ 825 1.3 lukem /* end of valar, etc. options */ 826 1.1 jtc } 827 1.1 jtc 828 1.3 lukem for (;;) 829 1.3 lukem /* prompt for player to affect */ 830 1.1 jtc { 831 1.3 lukem mvprintw(4, 0, "Who do you want to %s ? ", option); 832 1.3 lukem getstring(Databuf, SZ_DATABUF); 833 1.3 lukem truncstring(Databuf); 834 1.1 jtc 835 1.3 lukem if (Databuf[0] == '\0') 836 1.3 lukem userlist(TRUE); 837 1.3 lukem else 838 1.3 lukem break; 839 1.1 jtc } 840 1.1 jtc 841 1.3 lukem if (strcmp(Player.p_name, Databuf) != 0) 842 1.3 lukem /* name other than self */ 843 1.1 jtc { 844 1.3 lukem if ((loc = findname(Databuf, &Other)) >= 0L) { 845 1.3 lukem if (Other.p_tampered != T_OFF) { 846 1.3 lukem mvaddstr(5, 0, "That person has something pending already.\n"); 847 1.3 lukem return; 848 1.3 lukem } else { 849 1.3 lukem if (tamper == T_RELOCATE 850 1.3 lukem && CIRCLE(temp1, temp2) < CIRCLE(Other.p_x, Other.p_y) 851 1.3 lukem && !Wizard) 852 1.3 lukem mvaddstr(5, 0, "Cannot move someone closer to the Lord's Chamber.\n"); 853 1.3 lukem else { 854 1.3 lukem if (tamper == T_BESTOW) 855 1.3 lukem Player.p_gold -= floor(temp1); 856 1.3 lukem if (!Wizard && (tamper == T_HEAL || tamper == T_MONSTER || 857 1.3 lukem tamper == T_RELOCATE || tamper == T_BLESSED)) 858 1.3 lukem Player.p_age += N_AGE; /* age penalty */ 859 1.3 lukem Other.p_tampered = tamper; 860 1.3 lukem Other.p_1scratch = floor(temp1); 861 1.3 lukem Other.p_2scratch = floor(temp2); 862 1.3 lukem writerecord(&Other, loc); 863 1.3 lukem mvaddstr(5, 0, "It is done.\n"); 864 1.3 lukem } 865 1.3 lukem return; 866 1.3 lukem } 867 1.3 lukem } else 868 1.3 lukem /* player not found */ 869 1.3 lukem mvaddstr(5, 0, "There is no one by that name.\n"); 870 1.3 lukem } else 871 1.3 lukem /* self */ 872 1.3 lukem mvaddstr(5, 0, "You may not do it to yourself!\n"); 873 1.1 jtc } 874 1.1 jtc 875 1.3 lukem void 876 1.10 dholland writevoid(struct energyvoid *vp, long loc) 877 1.1 jtc { 878 1.1 jtc 879 1.5 jsm fseek(Energyvoidfp, loc, SEEK_SET); 880 1.3 lukem fwrite((char *) vp, SZ_VOIDSTRUCT, 1, Energyvoidfp); 881 1.3 lukem fflush(Energyvoidfp); 882 1.5 jsm fseek(Energyvoidfp, 0L, SEEK_SET); 883 1.1 jtc } 884 1.1 jtc 885 1.11 dholland static long 886 1.10 dholland allocvoid(void) 887 1.1 jtc { 888 1.3 lukem long loc = 0L; /* location of new energy void */ 889 1.1 jtc 890 1.5 jsm fseek(Energyvoidfp, 0L, SEEK_SET); 891 1.3 lukem while (fread((char *) &Enrgyvoid, SZ_VOIDSTRUCT, 1, Energyvoidfp) == 1) 892 1.3 lukem if (Enrgyvoid.ev_active) 893 1.3 lukem loc += SZ_VOIDSTRUCT; 894 1.3 lukem else 895 1.3 lukem break; 896 1.1 jtc 897 1.3 lukem return (loc); 898 1.1 jtc } 899