1 1.15 rillig /* $NetBSD: fight.c,v 1.15 2021/05/02 12:50:46 rillig Exp $ */ 2 1.2 cgd 3 1.1 jtc /* 4 1.1 jtc * fight.c Phantasia monster fighting routines 5 1.1 jtc */ 6 1.1 jtc 7 1.13 dholland #include <math.h> 8 1.13 dholland #include <setjmp.h> 9 1.13 dholland #include <stdio.h> 10 1.13 dholland #include <string.h> 11 1.13 dholland 12 1.13 dholland #include "macros.h" 13 1.13 dholland #include "phantdefs.h" 14 1.13 dholland #include "phantstruct.h" 15 1.13 dholland #include "phantglobs.h" 16 1.13 dholland 17 1.10 he #undef bool 18 1.9 ross #include <curses.h> 19 1.1 jtc 20 1.12 dholland static void awardtreasure(void); 21 1.12 dholland static void callmonster(int); 22 1.12 dholland static void cancelmonster(void); 23 1.12 dholland static void cursedtreasure(void); 24 1.12 dholland static void hitmonster(double); 25 1.12 dholland static void monsthits(void); 26 1.12 dholland static int pickmonster(void); 27 1.12 dholland static void playerhits(void); 28 1.12 dholland static void scramblestats(void); 29 1.12 dholland static void throwspell(void); 30 1.12 dholland 31 1.3 lukem void 32 1.11 dholland encounter(int particular) 33 1.1 jtc { 34 1.8 jsm volatile bool firsthit = Player.p_blessing; /* set if player gets 35 1.8 jsm * the first hit */ 36 1.8 jsm volatile int flockcnt = 1; /* how many time flocked */ 37 1.3 lukem 38 1.3 lukem /* let others know what we are doing */ 39 1.3 lukem Player.p_status = S_MONSTER; 40 1.3 lukem writerecord(&Player, Fileloc); 41 1.1 jtc 42 1.1 jtc #ifdef SYS5 43 1.3 lukem flushinp(); 44 1.1 jtc #endif 45 1.1 jtc 46 1.3 lukem Shield = 0.0; /* no shield up yet */ 47 1.1 jtc 48 1.3 lukem if (particular >= 0) 49 1.3 lukem /* monster is specified */ 50 1.3 lukem Whichmonster = particular; 51 1.3 lukem else 52 1.3 lukem /* pick random monster */ 53 1.3 lukem Whichmonster = pickmonster(); 54 1.1 jtc 55 1.3 lukem setjmp(Fightenv); /* this is to enable changing fight state */ 56 1.1 jtc 57 1.3 lukem move(6, 0); 58 1.3 lukem clrtobot(); /* clear bottom area of screen */ 59 1.1 jtc 60 1.3 lukem Lines = 9; 61 1.3 lukem callmonster(Whichmonster); /* set up monster to fight */ 62 1.1 jtc 63 1.3 lukem Luckout = FALSE; /* haven't tried to luckout yet */ 64 1.1 jtc 65 1.3 lukem if (Curmonster.m_type == SM_MORGOTH) 66 1.3 lukem mvprintw(4, 0, "You've encountered %s, Bane of the Council and Valar.\n", 67 1.3 lukem Enemyname); 68 1.1 jtc 69 1.3 lukem if (Curmonster.m_type == SM_UNICORN) { 70 1.3 lukem if (Player.p_virgin) { 71 1.3 lukem printw("You just subdued %s, thanks to the virgin.\n", Enemyname); 72 1.3 lukem Player.p_virgin = FALSE; 73 1.3 lukem } else { 74 1.3 lukem printw("You just saw %s running away!\n", Enemyname); 75 1.3 lukem Curmonster.m_experience = 0.0; 76 1.3 lukem Curmonster.m_treasuretype = 0; 77 1.3 lukem } 78 1.3 lukem } else 79 1.3 lukem /* not a special monster */ 80 1.3 lukem for (;;) 81 1.3 lukem /* print header, and arbitrate between player and 82 1.3 lukem * monster */ 83 1.1 jtc { 84 1.3 lukem mvprintw(6, 0, "You are being attacked by %s, EXP: %.0f (Size: %.0f)\n", 85 1.3 lukem Enemyname, Curmonster.m_experience, Circle); 86 1.3 lukem 87 1.3 lukem displaystats(); 88 1.3 lukem mvprintw(1, 26, "%20.0f", Player.p_energy + Shield); /* overprint energy */ 89 1.3 lukem readmessage(); 90 1.3 lukem 91 1.3 lukem if (Curmonster.m_type == SM_DARKLORD 92 1.3 lukem && Player.p_blessing 93 1.3 lukem && Player.p_charms > 0) 94 1.3 lukem /* overpower Dark Lord with blessing and charm */ 95 1.3 lukem { 96 1.3 lukem mvprintw(7, 0, "You just overpowered %s!", Enemyname); 97 1.3 lukem Lines = 8; 98 1.3 lukem Player.p_blessing = FALSE; 99 1.3 lukem --Player.p_charms; 100 1.3 lukem break; 101 1.3 lukem } 102 1.3 lukem /* allow paralyzed monster to wake up */ 103 1.3 lukem Curmonster.m_speed = MIN(Curmonster.m_speed + 1.0, Curmonster.m_maxspeed); 104 1.3 lukem 105 1.3 lukem if (drandom() * Curmonster.m_speed > drandom() * Player.p_speed 106 1.3 lukem /* monster is faster */ 107 1.3 lukem && Curmonster.m_type != SM_DARKLORD 108 1.3 lukem /* not D. L. */ 109 1.3 lukem && Curmonster.m_type != SM_SHRIEKER 110 1.3 lukem /* not mimic */ 111 1.3 lukem && !firsthit) 112 1.3 lukem /* monster gets a hit */ 113 1.3 lukem monsthits(); 114 1.3 lukem else 115 1.3 lukem /* player gets a hit */ 116 1.3 lukem { 117 1.3 lukem firsthit = FALSE; 118 1.3 lukem playerhits(); 119 1.3 lukem } 120 1.1 jtc 121 1.3 lukem refresh(); 122 1.1 jtc 123 1.3 lukem if (Lines > LINES - 2) 124 1.3 lukem /* near bottom of screen - pause */ 125 1.3 lukem { 126 1.3 lukem more(Lines); 127 1.3 lukem move(Lines = 8, 0); 128 1.3 lukem clrtobot(); 129 1.3 lukem } 130 1.3 lukem if (Player.p_energy <= 0.0) 131 1.3 lukem /* player died */ 132 1.3 lukem { 133 1.3 lukem more(Lines); 134 1.3 lukem death(Enemyname); 135 1.3 lukem cancelmonster(); 136 1.3 lukem break; /* fight ends if the player is saved 137 1.3 lukem * from death */ 138 1.3 lukem } 139 1.3 lukem if (Curmonster.m_energy <= 0.0) 140 1.3 lukem /* monster died */ 141 1.3 lukem break; 142 1.1 jtc } 143 1.1 jtc 144 1.3 lukem /* give player credit for killing monster */ 145 1.3 lukem Player.p_experience += Curmonster.m_experience; 146 1.1 jtc 147 1.3 lukem if (drandom() < Curmonster.m_flock / 100.0) 148 1.3 lukem /* monster flocks */ 149 1.3 lukem { 150 1.1 jtc more(Lines); 151 1.3 lukem ++flockcnt; 152 1.3 lukem longjmp(Fightenv, 0); 153 1.3 lukem /* NOTREACHED */ 154 1.3 lukem } else 155 1.3 lukem if (Circle > 1.0 156 1.3 lukem && Curmonster.m_treasuretype > 0 157 1.3 lukem && drandom() > 0.2 + pow(0.4, (double) (flockcnt / 3 + Circle / 3.0))) 158 1.3 lukem /* monster has treasure; this takes # of flocks and 159 1.3 lukem * size into account */ 160 1.1 jtc { 161 1.3 lukem more(Lines); 162 1.3 lukem awardtreasure(); 163 1.1 jtc } 164 1.3 lukem /* pause before returning */ 165 1.3 lukem getyx(stdscr, Lines, flockcnt); 166 1.3 lukem more(Lines + 1); 167 1.3 lukem 168 1.3 lukem Player.p_ring.ring_inuse = FALSE; /* not using ring */ 169 1.3 lukem 170 1.3 lukem /* clean up the screen */ 171 1.3 lukem move(4, 0); 172 1.3 lukem clrtobot(); 173 1.3 lukem } 174 1.1 jtc 175 1.12 dholland static int 176 1.11 dholland pickmonster(void) 177 1.3 lukem { 178 1.3 lukem if (Player.p_specialtype == SC_VALAR) 179 1.3 lukem /* even chance of any monster */ 180 1.3 lukem return ((int) ROLL(0.0, 100.0)); 181 1.3 lukem 182 1.3 lukem if (Marsh) 183 1.3 lukem /* water monsters */ 184 1.3 lukem return ((int) ROLL(0.0, 15.0)); 185 1.1 jtc 186 1.3 lukem else 187 1.3 lukem if (Circle > 24) 188 1.3 lukem /* even chance of all non-water monsters */ 189 1.3 lukem return ((int) ROLL(14.0, 86.0)); 190 1.1 jtc 191 1.3 lukem else 192 1.3 lukem if (Circle > 15) 193 1.3 lukem /* chance of all non-water monsters, weighted 194 1.3 lukem * toward middle */ 195 1.3 lukem return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 37.0))); 196 1.1 jtc 197 1.3 lukem else 198 1.3 lukem if (Circle > 8) 199 1.3 lukem /* not all non-water monsters, 200 1.3 lukem * weighted toward middle */ 201 1.3 lukem return ((int) (ROLL(0.0, 50.0) + ROLL(14.0, 26.0))); 202 1.1 jtc 203 1.3 lukem else 204 1.3 lukem if (Circle > 3) 205 1.3 lukem /* even chance of some tamer 206 1.3 lukem * non-water monsters */ 207 1.3 lukem return ((int) ROLL(14.0, 50.0)); 208 1.3 lukem 209 1.3 lukem else 210 1.3 lukem /* even chance of some of the 211 1.3 lukem * tamest non-water monsters */ 212 1.3 lukem return ((int) ROLL(14.0, 25.0)); 213 1.1 jtc } 214 1.1 jtc 215 1.12 dholland static void 216 1.11 dholland playerhits(void) 217 1.1 jtc { 218 1.3 lukem double inflict; /* damage inflicted */ 219 1.3 lukem int ch; /* input */ 220 1.1 jtc 221 1.3 lukem mvaddstr(7, 0, "1:Melee 2:Skirmish 3:Evade 4:Spell 5:Nick "); 222 1.3 lukem 223 1.4 veego if (!Luckout) { 224 1.3 lukem /* haven't tried to luckout yet */ 225 1.3 lukem if (Curmonster.m_type == SM_MORGOTH) 226 1.3 lukem /* cannot luckout against Morgoth */ 227 1.3 lukem addstr("6:Ally "); 228 1.3 lukem else 229 1.3 lukem addstr("6:Luckout "); 230 1.4 veego } 231 1.1 jtc 232 1.3 lukem if (Player.p_ring.ring_type != R_NONE) 233 1.3 lukem /* player has a ring */ 234 1.3 lukem addstr("7:Use Ring "); 235 1.1 jtc else 236 1.3 lukem clrtoeol(); 237 1.3 lukem 238 1.3 lukem ch = inputoption(); 239 1.1 jtc 240 1.3 lukem move(8, 0); 241 1.3 lukem clrtobot(); /* clear any messages from before */ 242 1.3 lukem Lines = 9; 243 1.3 lukem mvaddstr(4, 0, "\n\n"); /* clear status area */ 244 1.1 jtc 245 1.3 lukem switch (ch) { 246 1.1 jtc case 'T': /* timeout; lose turn */ 247 1.3 lukem break; 248 1.1 jtc 249 1.1 jtc case ' ': 250 1.1 jtc case '1': /* melee */ 251 1.3 lukem /* melee affects monster's energy and strength */ 252 1.3 lukem inflict = ROLL(Player.p_might / 2.0 + 5.0, 1.3 * Player.p_might) 253 1.3 lukem + (Player.p_ring.ring_inuse ? Player.p_might : 0.0); 254 1.3 lukem 255 1.3 lukem Curmonster.m_melee += inflict; 256 1.3 lukem Curmonster.m_strength = Curmonster.m_o_strength 257 1.3 lukem - Curmonster.m_melee / Curmonster.m_o_energy 258 1.3 lukem * Curmonster.m_o_strength / 4.0; 259 1.3 lukem hitmonster(inflict); 260 1.3 lukem break; 261 1.1 jtc 262 1.1 jtc case '2': /* skirmish */ 263 1.3 lukem /* skirmish affects monter's energy and speed */ 264 1.3 lukem inflict = ROLL(Player.p_might / 3.0 + 3.0, 1.1 * Player.p_might) 265 1.3 lukem + (Player.p_ring.ring_inuse ? Player.p_might : 0.0); 266 1.3 lukem 267 1.3 lukem Curmonster.m_skirmish += inflict; 268 1.3 lukem Curmonster.m_maxspeed = Curmonster.m_o_speed 269 1.3 lukem - Curmonster.m_skirmish / Curmonster.m_o_energy 270 1.3 lukem * Curmonster.m_o_speed / 4.0; 271 1.3 lukem hitmonster(inflict); 272 1.3 lukem break; 273 1.1 jtc 274 1.1 jtc case '3': /* evade */ 275 1.3 lukem /* use brains and speed to try to evade */ 276 1.3 lukem if ((Curmonster.m_type == SM_DARKLORD 277 1.3 lukem || Curmonster.m_type == SM_SHRIEKER 278 1.1 jtc /* can always run from D. L. and shrieker */ 279 1.3 lukem || drandom() * Player.p_speed * Player.p_brains 280 1.3 lukem > drandom() * Curmonster.m_speed * Curmonster.m_brains) 281 1.3 lukem && (Curmonster.m_type != SM_MIMIC)) 282 1.3 lukem /* cannot run from mimic */ 283 1.1 jtc { 284 1.3 lukem mvaddstr(Lines++, 0, "You got away!"); 285 1.3 lukem cancelmonster(); 286 1.3 lukem altercoordinates(0.0, 0.0, A_NEAR); 287 1.3 lukem } else 288 1.3 lukem mvprintw(Lines++, 0, "%s is still after you!", Enemyname); 289 1.1 jtc 290 1.3 lukem break; 291 1.1 jtc 292 1.1 jtc case 'M': 293 1.1 jtc case '4': /* magic spell */ 294 1.3 lukem throwspell(); 295 1.3 lukem break; 296 1.1 jtc 297 1.1 jtc case '5': /* nick */ 298 1.3 lukem /* hit 1 plus sword; give some experience */ 299 1.3 lukem inflict = 1.0 + Player.p_sword; 300 1.3 lukem Player.p_experience += floor(Curmonster.m_experience / 10.0); 301 1.3 lukem Curmonster.m_experience *= 0.92; 302 1.3 lukem /* monster gets meaner */ 303 1.3 lukem Curmonster.m_maxspeed += 2.0; 304 1.3 lukem Curmonster.m_speed = (Curmonster.m_speed < 0.0) ? 0.0 : Curmonster.m_speed + 2.0; 305 1.3 lukem if (Curmonster.m_type == SM_DARKLORD) 306 1.3 lukem /* Dark Lord; doesn't like to be nicked */ 307 1.1 jtc { 308 1.3 lukem mvprintw(Lines++, 0, 309 1.3 lukem "You hit %s %.0f times, and made him mad!", Enemyname, inflict); 310 1.3 lukem Player.p_quickness /= 2.0; 311 1.3 lukem altercoordinates(0.0, 0.0, A_FAR); 312 1.3 lukem cancelmonster(); 313 1.3 lukem } else 314 1.3 lukem hitmonster(inflict); 315 1.3 lukem break; 316 1.1 jtc 317 1.1 jtc case 'B': 318 1.3 lukem case '6': /* luckout */ 319 1.3 lukem if (Luckout) 320 1.3 lukem mvaddstr(Lines++, 0, "You already tried that."); 321 1.3 lukem else { 322 1.3 lukem Luckout = TRUE; 323 1.3 lukem if (Curmonster.m_type == SM_MORGOTH) 324 1.3 lukem /* Morgoth; ally */ 325 1.1 jtc { 326 1.3 lukem if (drandom() < Player.p_sin / 100.0) { 327 1.3 lukem mvprintw(Lines++, 0, "%s accepted!", Enemyname); 328 1.3 lukem cancelmonster(); 329 1.3 lukem } else 330 1.3 lukem mvaddstr(Lines++, 0, "Nope, he's not interested."); 331 1.3 lukem } else 332 1.3 lukem /* normal monster; use brains for success */ 333 1.1 jtc { 334 1.3 lukem if ((drandom() + 0.333) * Player.p_brains 335 1.3 lukem < (drandom() + 0.333) * Curmonster.m_brains) 336 1.3 lukem mvprintw(Lines++, 0, "You blew it, %s.", Player.p_name); 337 1.3 lukem else { 338 1.3 lukem mvaddstr(Lines++, 0, "You made it!"); 339 1.3 lukem Curmonster.m_energy = 0.0; 340 1.3 lukem } 341 1.1 jtc } 342 1.1 jtc } 343 1.3 lukem break; 344 1.1 jtc 345 1.1 jtc case '7': /* use ring */ 346 1.3 lukem if (Player.p_ring.ring_type != R_NONE) { 347 1.3 lukem mvaddstr(Lines++, 0, "Now using ring."); 348 1.3 lukem Player.p_ring.ring_inuse = TRUE; 349 1.3 lukem if (Player.p_ring.ring_type != R_DLREG) 350 1.3 lukem /* age ring */ 351 1.3 lukem --Player.p_ring.ring_duration; 352 1.1 jtc } 353 1.3 lukem break; 354 1.1 jtc } 355 1.1 jtc 356 1.1 jtc } 357 1.1 jtc 358 1.12 dholland static void 359 1.11 dholland monsthits(void) 360 1.1 jtc { 361 1.3 lukem double inflict; /* damage inflicted */ 362 1.3 lukem int ch; /* input */ 363 1.1 jtc 364 1.3 lukem switch (Curmonster.m_type) 365 1.3 lukem /* may be a special monster */ 366 1.1 jtc { 367 1.1 jtc case SM_DARKLORD: 368 1.3 lukem /* hits just enough to kill player */ 369 1.3 lukem inflict = (Player.p_energy + Shield) * 1.02; 370 1.3 lukem goto SPECIALHIT; 371 1.1 jtc 372 1.1 jtc case SM_SHRIEKER: 373 1.3 lukem /* call a big monster */ 374 1.3 lukem mvaddstr(Lines++, 0, 375 1.3 lukem "Shrieeeek!! You scared it, and it called one of its friends."); 376 1.3 lukem more(Lines); 377 1.3 lukem Whichmonster = (int) ROLL(70.0, 30.0); 378 1.3 lukem longjmp(Fightenv, 0); 379 1.3 lukem /* NOTREACHED */ 380 1.1 jtc 381 1.1 jtc case SM_BALROG: 382 1.3 lukem /* take experience away */ 383 1.3 lukem inflict = ROLL(10.0, Curmonster.m_strength); 384 1.3 lukem inflict = MIN(Player.p_experience, inflict); 385 1.3 lukem mvprintw(Lines++, 0, 386 1.3 lukem "%s took away %.0f experience points.", Enemyname, inflict); 387 1.3 lukem Player.p_experience -= inflict; 388 1.3 lukem return; 389 1.1 jtc 390 1.1 jtc case SM_FAERIES: 391 1.3 lukem if (Player.p_holywater > 0) 392 1.3 lukem /* holy water kills when monster tries to hit */ 393 1.1 jtc { 394 1.3 lukem mvprintw(Lines++, 0, "Your holy water killed it!"); 395 1.3 lukem --Player.p_holywater; 396 1.3 lukem Curmonster.m_energy = 0.0; 397 1.3 lukem return; 398 1.1 jtc } 399 1.3 lukem break; 400 1.1 jtc 401 1.1 jtc case SM_NONE: 402 1.3 lukem /* normal hit */ 403 1.3 lukem break; 404 1.1 jtc 405 1.1 jtc default: 406 1.3 lukem if (drandom() > 0.2) 407 1.3 lukem /* normal hit */ 408 1.3 lukem break; 409 1.1 jtc 410 1.3 lukem /* else special things */ 411 1.3 lukem switch (Curmonster.m_type) { 412 1.1 jtc case SM_LEANAN: 413 1.3 lukem /* takes some of the player's strength */ 414 1.3 lukem inflict = ROLL(1.0, (Circle - 1.0) / 2.0); 415 1.3 lukem inflict = MIN(Player.p_strength, inflict); 416 1.7 jdc mvprintw(Lines++, 0, "%s sapped %.0f of your strength!", 417 1.3 lukem Enemyname, inflict); 418 1.3 lukem Player.p_strength -= inflict; 419 1.3 lukem Player.p_might -= inflict; 420 1.3 lukem break; 421 1.1 jtc 422 1.1 jtc case SM_SARUMAN: 423 1.3 lukem if (Player.p_palantir) 424 1.3 lukem /* take away palantir */ 425 1.1 jtc { 426 1.3 lukem mvprintw(Lines++, 0, "Wormtongue stole your palantir!"); 427 1.3 lukem Player.p_palantir = FALSE; 428 1.3 lukem } else 429 1.3 lukem if (drandom() > 0.5) 430 1.3 lukem /* gems turn to gold */ 431 1.3 lukem { 432 1.3 lukem mvprintw(Lines++, 0, 433 1.3 lukem "%s transformed your gems into gold!", Enemyname); 434 1.3 lukem Player.p_gold += Player.p_gems; 435 1.3 lukem Player.p_gems = 0.0; 436 1.3 lukem } else 437 1.3 lukem /* scramble some stats */ 438 1.3 lukem { 439 1.3 lukem mvprintw(Lines++, 0, "%s scrambled your stats!", Enemyname); 440 1.3 lukem scramblestats(); 441 1.3 lukem } 442 1.3 lukem break; 443 1.1 jtc 444 1.1 jtc case SM_THAUMATURG: 445 1.3 lukem /* transport player */ 446 1.3 lukem mvprintw(Lines++, 0, "%s transported you!", Enemyname); 447 1.3 lukem altercoordinates(0.0, 0.0, A_FAR); 448 1.3 lukem cancelmonster(); 449 1.3 lukem break; 450 1.1 jtc 451 1.1 jtc case SM_VORTEX: 452 1.3 lukem /* suck up some mana */ 453 1.3 lukem inflict = ROLL(0, 7.5 * Circle); 454 1.3 lukem inflict = MIN(Player.p_mana, floor(inflict)); 455 1.3 lukem mvprintw(Lines++, 0, 456 1.3 lukem "%s sucked up %.0f of your mana!", Enemyname, inflict); 457 1.3 lukem Player.p_mana -= inflict; 458 1.3 lukem break; 459 1.1 jtc 460 1.1 jtc case SM_NAZGUL: 461 1.3 lukem /* try to take ring if player has one */ 462 1.3 lukem if (Player.p_ring.ring_type != R_NONE) 463 1.3 lukem /* player has a ring */ 464 1.1 jtc { 465 1.3 lukem mvaddstr(Lines++, 0, "Will you relinguish your ring ? "); 466 1.3 lukem ch = getanswer("YN", FALSE); 467 1.3 lukem if (ch == 'Y') 468 1.3 lukem /* take ring away */ 469 1.3 lukem { 470 1.3 lukem Player.p_ring.ring_type = R_NONE; 471 1.3 lukem Player.p_ring.ring_inuse = FALSE; 472 1.3 lukem cancelmonster(); 473 1.3 lukem break; 474 1.3 lukem } 475 1.1 jtc } 476 1.3 lukem /* otherwise, take some brains */ 477 1.3 lukem mvprintw(Lines++, 0, 478 1.3 lukem "%s neutralized 1/5 of your brain!", Enemyname); 479 1.3 lukem Player.p_brains *= 0.8; 480 1.3 lukem break; 481 1.1 jtc 482 1.1 jtc case SM_TIAMAT: 483 1.3 lukem /* take some gold and gems */ 484 1.3 lukem mvprintw(Lines++, 0, 485 1.3 lukem "%s took half your gold and gems and flew off.", Enemyname); 486 1.3 lukem Player.p_gold /= 2.0; 487 1.3 lukem Player.p_gems /= 2.0; 488 1.3 lukem cancelmonster(); 489 1.3 lukem break; 490 1.1 jtc 491 1.1 jtc case SM_KOBOLD: 492 1.3 lukem /* steal a gold piece and run */ 493 1.3 lukem mvprintw(Lines++, 0, 494 1.3 lukem "%s stole one gold piece and ran away.", Enemyname); 495 1.3 lukem Player.p_gold = MAX(0.0, Player.p_gold - 1.0); 496 1.3 lukem cancelmonster(); 497 1.3 lukem break; 498 1.1 jtc 499 1.1 jtc case SM_SHELOB: 500 1.3 lukem /* bite and (medium) poison */ 501 1.3 lukem mvprintw(Lines++, 0, 502 1.3 lukem "%s has bitten and poisoned you!", Enemyname); 503 1.3 lukem Player.p_poison -= 1.0; 504 1.3 lukem break; 505 1.1 jtc 506 1.1 jtc case SM_LAMPREY: 507 1.3 lukem /* bite and (small) poison */ 508 1.3 lukem mvprintw(Lines++, 0, "%s bit and poisoned you!", Enemyname); 509 1.3 lukem Player.p_poison += 0.25; 510 1.3 lukem break; 511 1.1 jtc 512 1.1 jtc case SM_BONNACON: 513 1.3 lukem /* fart and run */ 514 1.3 lukem mvprintw(Lines++, 0, "%s farted and scampered off.", Enemyname); 515 1.3 lukem Player.p_energy /= 2.0; /* damage from fumes */ 516 1.3 lukem cancelmonster(); 517 1.3 lukem break; 518 1.1 jtc 519 1.1 jtc case SM_SMEAGOL: 520 1.3 lukem if (Player.p_ring.ring_type != R_NONE) 521 1.3 lukem /* try to steal ring */ 522 1.1 jtc { 523 1.3 lukem mvprintw(Lines++, 0, 524 1.3 lukem "%s tried to steal your ring, ", Enemyname); 525 1.3 lukem if (drandom() > 0.1) 526 1.3 lukem addstr("but was unsuccessful."); 527 1.3 lukem else { 528 1.3 lukem addstr("and ran away with it!"); 529 1.3 lukem Player.p_ring.ring_type = R_NONE; 530 1.3 lukem cancelmonster(); 531 1.3 lukem } 532 1.1 jtc } 533 1.3 lukem break; 534 1.1 jtc 535 1.1 jtc case SM_SUCCUBUS: 536 1.3 lukem /* inflict damage through shield */ 537 1.3 lukem inflict = ROLL(15.0, Circle * 10.0); 538 1.3 lukem inflict = MIN(inflict, Player.p_energy); 539 1.3 lukem mvprintw(Lines++, 0, "%s sapped %.0f of your energy.", 540 1.3 lukem Enemyname, inflict); 541 1.3 lukem Player.p_energy -= inflict; 542 1.3 lukem break; 543 1.1 jtc 544 1.1 jtc case SM_CERBERUS: 545 1.3 lukem /* take all metal treasures */ 546 1.3 lukem mvprintw(Lines++, 0, 547 1.3 lukem "%s took all your metal treasures!", Enemyname); 548 1.3 lukem Player.p_crowns = 0; 549 1.3 lukem Player.p_sword = 550 1.3 lukem Player.p_shield = 551 1.3 lukem Player.p_gold = 0.0; 552 1.3 lukem cancelmonster(); 553 1.3 lukem break; 554 1.1 jtc 555 1.1 jtc case SM_UNGOLIANT: 556 1.3 lukem /* (large) poison and take a quickness */ 557 1.3 lukem mvprintw(Lines++, 0, 558 1.3 lukem "%s poisoned you, and took one quik.", Enemyname); 559 1.3 lukem Player.p_poison += 5.0; 560 1.3 lukem Player.p_quickness -= 1.0; 561 1.3 lukem break; 562 1.1 jtc 563 1.1 jtc case SM_JABBERWOCK: 564 1.3 lukem /* fly away, and leave either a Jubjub bird or 565 1.3 lukem * Bonnacon */ 566 1.3 lukem mvprintw(Lines++, 0, 567 1.3 lukem "%s flew away, and left you to contend with one of its friends.", 568 1.3 lukem Enemyname); 569 1.6 jdolecek Whichmonster = 55 + ((drandom() > 0.5) ? 22 : 0); 570 1.3 lukem longjmp(Fightenv, 0); 571 1.3 lukem /* NOTREACHED */ 572 1.1 jtc 573 1.1 jtc case SM_TROLL: 574 1.3 lukem /* partially regenerate monster */ 575 1.3 lukem mvprintw(Lines++, 0, 576 1.3 lukem "%s partially regenerated his energy.!", Enemyname); 577 1.3 lukem Curmonster.m_energy += 578 1.3 lukem floor((Curmonster.m_o_energy - Curmonster.m_energy) / 2.0); 579 1.3 lukem Curmonster.m_strength = Curmonster.m_o_strength; 580 1.3 lukem Curmonster.m_melee = Curmonster.m_skirmish = 0.0; 581 1.3 lukem Curmonster.m_maxspeed = Curmonster.m_o_speed; 582 1.3 lukem break; 583 1.1 jtc 584 1.1 jtc case SM_WRAITH: 585 1.3 lukem if (!Player.p_blindness) 586 1.3 lukem /* make blind */ 587 1.1 jtc { 588 1.3 lukem mvprintw(Lines++, 0, "%s blinded you!", Enemyname); 589 1.3 lukem Player.p_blindness = TRUE; 590 1.3 lukem Enemyname = "A monster"; 591 1.1 jtc } 592 1.3 lukem break; 593 1.1 jtc } 594 1.3 lukem return; 595 1.1 jtc } 596 1.1 jtc 597 1.3 lukem /* fall through to here if monster inflicts a normal hit */ 598 1.3 lukem inflict = drandom() * Curmonster.m_strength + 0.5; 599 1.1 jtc SPECIALHIT: 600 1.3 lukem mvprintw(Lines++, 0, "%s hit you %.0f times!", Enemyname, inflict); 601 1.1 jtc 602 1.3 lukem if ((Shield -= inflict) < 0) { 603 1.3 lukem Player.p_energy += Shield; 604 1.3 lukem Shield = 0.0; 605 1.1 jtc } 606 1.1 jtc } 607 1.1 jtc 608 1.12 dholland static void 609 1.11 dholland cancelmonster(void) 610 1.1 jtc { 611 1.3 lukem Curmonster.m_energy = 0.0; 612 1.3 lukem Curmonster.m_experience = 0.0; 613 1.3 lukem Curmonster.m_treasuretype = 0; 614 1.3 lukem Curmonster.m_flock = 0.0; 615 1.1 jtc } 616 1.1 jtc 617 1.12 dholland static void 618 1.11 dholland hitmonster(double inflict) 619 1.1 jtc { 620 1.3 lukem mvprintw(Lines++, 0, "You hit %s %.0f times!", Enemyname, inflict); 621 1.3 lukem Curmonster.m_energy -= inflict; 622 1.3 lukem if (Curmonster.m_energy > 0.0) { 623 1.3 lukem if (Curmonster.m_type == SM_DARKLORD || Curmonster.m_type == SM_SHRIEKER) 624 1.3 lukem /* special monster didn't die */ 625 1.3 lukem monsthits(); 626 1.3 lukem } else 627 1.3 lukem /* monster died. print message. */ 628 1.1 jtc { 629 1.3 lukem if (Curmonster.m_type == SM_MORGOTH) 630 1.3 lukem mvaddstr(Lines++, 0, "You have defeated Morgoth, but he may return. . ."); 631 1.3 lukem else 632 1.3 lukem /* all other types of monsters */ 633 1.3 lukem { 634 1.3 lukem mvprintw(Lines++, 0, "You killed it. Good work, %s.", Player.p_name); 635 1.3 lukem 636 1.3 lukem if (Curmonster.m_type == SM_MIMIC 637 1.3 lukem && strcmp(Curmonster.m_name, "A Mimic") != 0 638 1.3 lukem && !Player.p_blindness) 639 1.3 lukem mvaddstr(Lines++, 0, "The body slowly changes into the form of a mimic."); 640 1.3 lukem } 641 1.1 jtc } 642 1.1 jtc } 643 1.1 jtc 644 1.12 dholland static void 645 1.11 dholland throwspell(void) 646 1.1 jtc { 647 1.3 lukem double inflict; /* damage inflicted */ 648 1.3 lukem double dtemp; /* for dtemporary calculations */ 649 1.3 lukem int ch; /* input */ 650 1.3 lukem 651 1.3 lukem inflict = 0; 652 1.3 lukem mvaddstr(7, 0, "\n\n"); /* clear menu area */ 653 1.3 lukem 654 1.3 lukem if (Player.p_magiclvl >= ML_ALLORNOTHING) 655 1.3 lukem mvaddstr(7, 0, "1:All or Nothing "); 656 1.3 lukem if (Player.p_magiclvl >= ML_MAGICBOLT) 657 1.3 lukem addstr("2:Magic Bolt "); 658 1.3 lukem if (Player.p_magiclvl >= ML_FORCEFIELD) 659 1.3 lukem addstr("3:Force Field "); 660 1.3 lukem if (Player.p_magiclvl >= ML_XFORM) 661 1.3 lukem addstr("4:Transform "); 662 1.3 lukem if (Player.p_magiclvl >= ML_INCRMIGHT) 663 1.3 lukem addstr("5:Increase Might\n"); 664 1.3 lukem if (Player.p_magiclvl >= ML_INVISIBLE) 665 1.3 lukem mvaddstr(8, 0, "6:Invisibility "); 666 1.3 lukem if (Player.p_magiclvl >= ML_XPORT) 667 1.3 lukem addstr("7:Transport "); 668 1.3 lukem if (Player.p_magiclvl >= ML_PARALYZE) 669 1.3 lukem addstr("8:Paralyze "); 670 1.3 lukem if (Player.p_specialtype >= SC_COUNCIL) 671 1.3 lukem addstr("9:Specify"); 672 1.3 lukem mvaddstr(4, 0, "Spell ? "); 673 1.3 lukem 674 1.3 lukem ch = getanswer(" ", TRUE); 675 1.3 lukem 676 1.3 lukem mvaddstr(7, 0, "\n\n"); /* clear menu area */ 677 1.3 lukem 678 1.3 lukem if (Curmonster.m_type == SM_MORGOTH && ch != '3') 679 1.3 lukem /* can only throw force field against Morgoth */ 680 1.3 lukem ILLSPELL(); 681 1.3 lukem else 682 1.3 lukem switch (ch) { 683 1.3 lukem case '1': /* all or nothing */ 684 1.3 lukem if (drandom() < 0.25) 685 1.3 lukem /* success */ 686 1.3 lukem { 687 1.3 lukem inflict = Curmonster.m_energy * 1.01 + 1.0; 688 1.1 jtc 689 1.3 lukem if (Curmonster.m_type == SM_DARKLORD) 690 1.3 lukem /* all or nothing doesn't quite work 691 1.3 lukem * against D. L. */ 692 1.3 lukem inflict *= 0.9; 693 1.3 lukem } else 694 1.3 lukem /* failure -- monster gets stronger and 695 1.3 lukem * quicker */ 696 1.3 lukem { 697 1.3 lukem Curmonster.m_o_strength = Curmonster.m_strength *= 2.0; 698 1.3 lukem Curmonster.m_maxspeed *= 2.0; 699 1.3 lukem Curmonster.m_o_speed *= 2.0; 700 1.1 jtc 701 1.3 lukem /* paralyzed monsters wake up a bit */ 702 1.3 lukem Curmonster.m_speed = MAX(1.0, Curmonster.m_speed * 2.0); 703 1.1 jtc } 704 1.1 jtc 705 1.3 lukem if (Player.p_mana >= MM_ALLORNOTHING) 706 1.3 lukem /* take a mana if player has one */ 707 1.3 lukem Player.p_mana -= MM_ALLORNOTHING; 708 1.1 jtc 709 1.3 lukem hitmonster(inflict); 710 1.3 lukem break; 711 1.3 lukem 712 1.3 lukem case '2': /* magic bolt */ 713 1.3 lukem if (Player.p_magiclvl < ML_MAGICBOLT) 714 1.3 lukem ILLSPELL(); 715 1.3 lukem else { 716 1.3 lukem do 717 1.3 lukem /* prompt for amount to expend */ 718 1.3 lukem { 719 1.3 lukem mvaddstr(4, 0, "How much mana for bolt? "); 720 1.3 lukem dtemp = floor(infloat()); 721 1.3 lukem } 722 1.3 lukem while (dtemp < 0.0 || dtemp > Player.p_mana); 723 1.3 lukem 724 1.3 lukem Player.p_mana -= dtemp; 725 1.3 lukem 726 1.3 lukem if (Curmonster.m_type == SM_DARKLORD) 727 1.3 lukem /* magic bolts don't work against D. 728 1.3 lukem * L. */ 729 1.3 lukem inflict = 0.0; 730 1.3 lukem else 731 1.3 lukem inflict = dtemp * ROLL(15.0, sqrt(Player.p_magiclvl / 3.0 + 1.0)); 732 1.3 lukem mvaddstr(5, 0, "Magic Bolt fired!\n"); 733 1.3 lukem hitmonster(inflict); 734 1.3 lukem } 735 1.3 lukem break; 736 1.1 jtc 737 1.3 lukem case '3': /* force field */ 738 1.3 lukem if (Player.p_magiclvl < ML_FORCEFIELD) 739 1.3 lukem ILLSPELL(); 740 1.3 lukem else 741 1.3 lukem if (Player.p_mana < MM_FORCEFIELD) 742 1.3 lukem NOMANA(); 743 1.3 lukem else { 744 1.3 lukem Player.p_mana -= MM_FORCEFIELD; 745 1.3 lukem Shield = (Player.p_maxenergy + Player.p_shield) * 4.2 + 45.0; 746 1.3 lukem mvaddstr(5, 0, "Force Field up.\n"); 747 1.3 lukem } 748 1.3 lukem break; 749 1.1 jtc 750 1.3 lukem case '4': /* transform */ 751 1.3 lukem if (Player.p_magiclvl < ML_XFORM) 752 1.3 lukem ILLSPELL(); 753 1.3 lukem else 754 1.3 lukem if (Player.p_mana < MM_XFORM) 755 1.3 lukem NOMANA(); 756 1.3 lukem else { 757 1.3 lukem Player.p_mana -= MM_XFORM; 758 1.3 lukem Whichmonster = (int) ROLL(0.0, 100.0); 759 1.3 lukem longjmp(Fightenv, 0); 760 1.3 lukem /* NOTREACHED */ 761 1.3 lukem } 762 1.3 lukem break; 763 1.1 jtc 764 1.3 lukem case '5': /* increase might */ 765 1.3 lukem if (Player.p_magiclvl < ML_INCRMIGHT) 766 1.3 lukem ILLSPELL(); 767 1.3 lukem else 768 1.3 lukem if (Player.p_mana < MM_INCRMIGHT) 769 1.3 lukem NOMANA(); 770 1.3 lukem else { 771 1.3 lukem Player.p_mana -= MM_INCRMIGHT; 772 1.3 lukem Player.p_might += 773 1.3 lukem (1.2 * (Player.p_strength + Player.p_sword) 774 1.3 lukem + 5.0 - Player.p_might) / 2.0; 775 1.3 lukem mvprintw(5, 0, "New strength: %.0f\n", Player.p_might); 776 1.3 lukem } 777 1.3 lukem break; 778 1.1 jtc 779 1.3 lukem case '6': /* invisible */ 780 1.3 lukem if (Player.p_magiclvl < ML_INVISIBLE) 781 1.3 lukem ILLSPELL(); 782 1.3 lukem else 783 1.3 lukem if (Player.p_mana < MM_INVISIBLE) 784 1.3 lukem NOMANA(); 785 1.3 lukem else { 786 1.3 lukem Player.p_mana -= MM_INVISIBLE; 787 1.3 lukem Player.p_speed += 788 1.3 lukem (1.2 * (Player.p_quickness + Player.p_quksilver) 789 1.3 lukem + 5.0 - Player.p_speed) / 2.0; 790 1.3 lukem mvprintw(5, 0, "New quickness: %.0f\n", Player.p_speed); 791 1.3 lukem } 792 1.3 lukem break; 793 1.1 jtc 794 1.3 lukem case '7': /* transport */ 795 1.3 lukem if (Player.p_magiclvl < ML_XPORT) 796 1.3 lukem ILLSPELL(); 797 1.3 lukem else 798 1.3 lukem if (Player.p_mana < MM_XPORT) 799 1.3 lukem NOMANA(); 800 1.3 lukem else { 801 1.3 lukem Player.p_mana -= MM_XPORT; 802 1.3 lukem if (Player.p_brains + Player.p_magiclvl 803 1.3 lukem < Curmonster.m_experience / 200.0 * drandom()) { 804 1.3 lukem mvaddstr(5, 0, "Transport backfired!\n"); 805 1.3 lukem altercoordinates(0.0, 0.0, A_FAR); 806 1.3 lukem cancelmonster(); 807 1.3 lukem } else { 808 1.3 lukem mvprintw(5, 0, "%s is transported.\n", Enemyname); 809 1.3 lukem if (drandom() < 0.3) 810 1.3 lukem /* monster didn't drop 811 1.3 lukem * its treasure */ 812 1.3 lukem Curmonster.m_treasuretype = 0; 813 1.1 jtc 814 1.3 lukem Curmonster.m_energy = 0.0; 815 1.3 lukem } 816 1.3 lukem } 817 1.3 lukem break; 818 1.1 jtc 819 1.3 lukem case '8': /* paralyze */ 820 1.3 lukem if (Player.p_magiclvl < ML_PARALYZE) 821 1.3 lukem ILLSPELL(); 822 1.3 lukem else 823 1.3 lukem if (Player.p_mana < MM_PARALYZE) 824 1.3 lukem NOMANA(); 825 1.3 lukem else { 826 1.3 lukem Player.p_mana -= MM_PARALYZE; 827 1.3 lukem if (Player.p_magiclvl > 828 1.3 lukem Curmonster.m_experience / 1000.0 * drandom()) { 829 1.3 lukem mvprintw(5, 0, "%s is held.\n", Enemyname); 830 1.3 lukem Curmonster.m_speed = -2.0; 831 1.3 lukem } else 832 1.3 lukem mvaddstr(5, 0, "Monster unaffected.\n"); 833 1.3 lukem } 834 1.3 lukem break; 835 1.1 jtc 836 1.3 lukem case '9': /* specify */ 837 1.3 lukem if (Player.p_specialtype < SC_COUNCIL) 838 1.3 lukem ILLSPELL(); 839 1.3 lukem else 840 1.3 lukem if (Player.p_mana < MM_SPECIFY) 841 1.3 lukem NOMANA(); 842 1.3 lukem else { 843 1.3 lukem Player.p_mana -= MM_SPECIFY; 844 1.3 lukem mvaddstr(5, 0, "Which monster do you want [0-99] ? "); 845 1.3 lukem Whichmonster = (int) infloat(); 846 1.3 lukem Whichmonster = MAX(0, MIN(99, Whichmonster)); 847 1.3 lukem longjmp(Fightenv, 0); 848 1.3 lukem /* NOTREACHED */ 849 1.3 lukem } 850 1.3 lukem break; 851 1.3 lukem } 852 1.1 jtc } 853 1.1 jtc 854 1.12 dholland static void 855 1.11 dholland callmonster(int which) 856 1.1 jtc { 857 1.3 lukem struct monster Othermonster; /* to find a name for mimics */ 858 1.1 jtc 859 1.3 lukem which = MIN(which, 99); /* make sure within range */ 860 1.1 jtc 861 1.3 lukem /* fill structure */ 862 1.5 jsm fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, SEEK_SET); 863 1.3 lukem fread((char *) &Curmonster, SZ_MONSTERSTRUCT, 1, Monstfp); 864 1.1 jtc 865 1.3 lukem /* handle some special monsters */ 866 1.3 lukem if (Curmonster.m_type == SM_MODNAR) { 867 1.3 lukem if (Player.p_specialtype < SC_COUNCIL) 868 1.3 lukem /* randomize some stats */ 869 1.3 lukem { 870 1.3 lukem Curmonster.m_strength *= drandom() + 0.5; 871 1.3 lukem Curmonster.m_brains *= drandom() + 0.5; 872 1.3 lukem Curmonster.m_speed *= drandom() + 0.5; 873 1.3 lukem Curmonster.m_energy *= drandom() + 0.5; 874 1.3 lukem Curmonster.m_experience *= drandom() + 0.5; 875 1.3 lukem Curmonster.m_treasuretype = 876 1.3 lukem (int) ROLL(0.0, (double) Curmonster.m_treasuretype); 877 1.3 lukem } else 878 1.3 lukem /* make Modnar into Morgoth */ 879 1.3 lukem { 880 1.3 lukem strcpy(Curmonster.m_name, "Morgoth"); 881 1.3 lukem Curmonster.m_strength = drandom() * (Player.p_maxenergy + Player.p_shield) / 1.4 882 1.3 lukem + drandom() * (Player.p_maxenergy + Player.p_shield) / 1.5; 883 1.3 lukem Curmonster.m_brains = Player.p_brains; 884 1.3 lukem Curmonster.m_energy = Player.p_might * 30.0; 885 1.3 lukem Curmonster.m_type = SM_MORGOTH; 886 1.3 lukem Curmonster.m_speed = Player.p_speed * 1.1 887 1.6 jdolecek + ((Player.p_specialtype == SC_EXVALAR) ? Player.p_speed : 0.0); 888 1.3 lukem Curmonster.m_flock = 0.0; 889 1.3 lukem Curmonster.m_treasuretype = 0; 890 1.3 lukem Curmonster.m_experience = 0.0; 891 1.3 lukem } 892 1.3 lukem } else 893 1.3 lukem if (Curmonster.m_type == SM_MIMIC) 894 1.3 lukem /* pick another name */ 895 1.3 lukem { 896 1.3 lukem which = (int) ROLL(0.0, 100.0); 897 1.5 jsm fseek(Monstfp, (long) which * (long) SZ_MONSTERSTRUCT, SEEK_SET); 898 1.3 lukem fread(&Othermonster, SZ_MONSTERSTRUCT, 1, Monstfp); 899 1.3 lukem strcpy(Curmonster.m_name, Othermonster.m_name); 900 1.3 lukem } 901 1.3 lukem truncstring(Curmonster.m_name); 902 1.1 jtc 903 1.3 lukem if (Curmonster.m_type != SM_MORGOTH) 904 1.3 lukem /* adjust stats based on which circle player is in */ 905 1.1 jtc { 906 1.3 lukem Curmonster.m_strength *= (1.0 + Circle / 2.0); 907 1.3 lukem Curmonster.m_brains *= Circle; 908 1.3 lukem Curmonster.m_speed += Circle * 1.e-9; 909 1.3 lukem Curmonster.m_energy *= Circle; 910 1.3 lukem Curmonster.m_experience *= Circle; 911 1.1 jtc } 912 1.3 lukem if (Player.p_blindness) 913 1.3 lukem /* cannot see monster if blind */ 914 1.3 lukem Enemyname = "A monster"; 915 1.3 lukem else 916 1.3 lukem Enemyname = Curmonster.m_name; 917 1.1 jtc 918 1.3 lukem if (Player.p_speed <= 0.0) 919 1.3 lukem /* make Player.p_speed positive */ 920 1.1 jtc { 921 1.3 lukem Curmonster.m_speed += -Player.p_speed; 922 1.3 lukem Player.p_speed = 1.0; 923 1.1 jtc } 924 1.3 lukem /* fill up the rest of the structure */ 925 1.3 lukem Curmonster.m_o_strength = Curmonster.m_strength; 926 1.3 lukem Curmonster.m_o_speed = Curmonster.m_maxspeed = Curmonster.m_speed; 927 1.3 lukem Curmonster.m_o_energy = Curmonster.m_energy; 928 1.3 lukem Curmonster.m_melee = Curmonster.m_skirmish = 0.0; 929 1.1 jtc } 930 1.1 jtc 931 1.12 dholland static void 932 1.11 dholland awardtreasure(void) 933 1.1 jtc { 934 1.3 lukem int whichtreasure; /* calculated treasure to grant */ 935 1.3 lukem int temp; /* temporary */ 936 1.3 lukem int ch; /* input */ 937 1.3 lukem double treasuretype; /* monster's treasure type */ 938 1.3 lukem double gold = 0.0; /* gold awarded */ 939 1.3 lukem double gems = 0.0; /* gems awarded */ 940 1.3 lukem double dtemp; /* for temporary calculations */ 941 1.3 lukem 942 1.3 lukem whichtreasure = (int) ROLL(1.0, 3.0); /* pick a treasure */ 943 1.3 lukem treasuretype = (double) Curmonster.m_treasuretype; 944 1.3 lukem 945 1.3 lukem move(4, 0); 946 1.3 lukem clrtobot(); 947 1.3 lukem move(6, 0); 948 1.1 jtc 949 1.3 lukem if (drandom() > 0.65) 950 1.3 lukem /* gold and gems */ 951 1.1 jtc { 952 1.3 lukem if (Curmonster.m_treasuretype > 7) 953 1.3 lukem /* gems */ 954 1.3 lukem { 955 1.3 lukem gems = ROLL(1.0, (treasuretype - 7.0) 956 1.3 lukem * (treasuretype - 7.0) * (Circle - 1.0) / 4.0); 957 1.3 lukem printw("You have discovered %.0f gems!", gems); 958 1.3 lukem } else 959 1.3 lukem /* gold */ 960 1.1 jtc { 961 1.3 lukem gold = ROLL(treasuretype * 10.0, treasuretype 962 1.3 lukem * treasuretype * 10.0 * (Circle - 1.0)); 963 1.3 lukem printw("You have found %.0f gold pieces.", gold); 964 1.1 jtc } 965 1.1 jtc 966 1.3 lukem addstr(" Do you want to pick them up ? "); 967 1.3 lukem ch = getanswer("NY", FALSE); 968 1.3 lukem addstr("\n\n"); 969 1.3 lukem 970 1.4 veego if (ch == 'Y') { 971 1.3 lukem if (drandom() < treasuretype / 35.0 + 0.04) 972 1.3 lukem /* cursed */ 973 1.3 lukem { 974 1.3 lukem addstr("They were cursed!\n"); 975 1.3 lukem cursedtreasure(); 976 1.3 lukem } else 977 1.3 lukem collecttaxes(gold, gems); 978 1.4 veego } 979 1.1 jtc 980 1.1 jtc return; 981 1.3 lukem } else 982 1.3 lukem /* other treasures */ 983 1.3 lukem { 984 1.3 lukem addstr("You have found some treasure. Do you want to inspect it ? "); 985 1.3 lukem ch = getanswer("NY", FALSE); 986 1.3 lukem addstr("\n\n"); 987 1.1 jtc 988 1.3 lukem if (ch != 'Y') 989 1.3 lukem return; 990 1.3 lukem else 991 1.3 lukem if (drandom() < 0.08 && Curmonster.m_treasuretype != 4) { 992 1.3 lukem addstr("It was cursed!\n"); 993 1.3 lukem cursedtreasure(); 994 1.3 lukem return; 995 1.3 lukem } else 996 1.3 lukem switch (Curmonster.m_treasuretype) { 997 1.3 lukem case 1: /* treasure type 1 */ 998 1.3 lukem switch (whichtreasure) { 999 1.3 lukem case 1: 1000 1.3 lukem addstr("You've discovered a power booster!\n"); 1001 1.3 lukem Player.p_mana += ROLL(Circle * 4.0, Circle * 30.0); 1002 1.3 lukem break; 1003 1.3 lukem 1004 1.3 lukem case 2: 1005 1.3 lukem addstr("You have encountered a druid.\n"); 1006 1.3 lukem Player.p_experience += 1007 1.3 lukem ROLL(0.0, 2000.0 + Circle * 400.0); 1008 1.3 lukem break; 1009 1.3 lukem 1010 1.3 lukem case 3: 1011 1.3 lukem addstr("You have found a holy orb.\n"); 1012 1.3 lukem Player.p_sin = MAX(0.0, Player.p_sin - 0.25); 1013 1.3 lukem break; 1014 1.3 lukem } 1015 1.3 lukem break; 1016 1.3 lukem /* end treasure type 1 */ 1017 1.1 jtc 1018 1.3 lukem case 2: /* treasure type 2 */ 1019 1.3 lukem switch (whichtreasure) { 1020 1.3 lukem case 1: 1021 1.3 lukem addstr("You have found an amulet.\n"); 1022 1.3 lukem ++Player.p_amulets; 1023 1.3 lukem break; 1024 1.3 lukem 1025 1.3 lukem case 2: 1026 1.3 lukem addstr("You've found some holy water!\n"); 1027 1.3 lukem ++Player.p_holywater; 1028 1.3 lukem break; 1029 1.3 lukem 1030 1.3 lukem case 3: 1031 1.3 lukem addstr("You've met a hermit!\n"); 1032 1.3 lukem Player.p_sin *= 0.75; 1033 1.3 lukem Player.p_mana += 12.0 * Circle; 1034 1.3 lukem break; 1035 1.3 lukem } 1036 1.3 lukem break; 1037 1.3 lukem /* end treasure type 2 */ 1038 1.1 jtc 1039 1.3 lukem case 3: /* treasure type 3 */ 1040 1.3 lukem switch (whichtreasure) { 1041 1.3 lukem case 1: 1042 1.3 lukem dtemp = ROLL(7.0, 30.0 + Circle / 10.0); 1043 1.3 lukem printw("You've found a +%.0f shield!\n", dtemp); 1044 1.3 lukem if (dtemp >= Player.p_shield) 1045 1.3 lukem Player.p_shield = dtemp; 1046 1.3 lukem else 1047 1.3 lukem SOMEBETTER(); 1048 1.3 lukem break; 1049 1.3 lukem 1050 1.3 lukem case 2: 1051 1.3 lukem addstr("You have rescued a virgin. Will you be honorable ? "); 1052 1.3 lukem ch = getanswer("NY", FALSE); 1053 1.3 lukem addstr("\n\n"); 1054 1.3 lukem if (ch == 'Y') 1055 1.3 lukem Player.p_virgin = TRUE; 1056 1.3 lukem else { 1057 1.3 lukem Player.p_experience += 2000.0 * Circle; 1058 1.3 lukem ++Player.p_sin; 1059 1.3 lukem } 1060 1.3 lukem break; 1061 1.3 lukem 1062 1.3 lukem case 3: 1063 1.3 lukem addstr("You've discovered some athelas!\n"); 1064 1.3 lukem --Player.p_poison; 1065 1.3 lukem break; 1066 1.3 lukem } 1067 1.3 lukem break; 1068 1.3 lukem /* end treasure type 3 */ 1069 1.1 jtc 1070 1.3 lukem case 4: /* treasure type 4 */ 1071 1.3 lukem addstr("You've found a scroll. Will you read it ? "); 1072 1.3 lukem ch = getanswer("NY", FALSE); 1073 1.3 lukem addstr("\n\n"); 1074 1.3 lukem 1075 1.3 lukem if (ch == 'Y') 1076 1.3 lukem switch ((int) ROLL(1, 6)) { 1077 1.3 lukem case 1: 1078 1.3 lukem addstr("It throws up a shield for you next monster.\n"); 1079 1.3 lukem getyx(stdscr, whichtreasure, ch); 1080 1.3 lukem more(whichtreasure); 1081 1.3 lukem Shield = 1082 1.3 lukem (Player.p_maxenergy + Player.p_energy) * 5.5 + Circle * 50.0; 1083 1.3 lukem Whichmonster = pickmonster(); 1084 1.3 lukem longjmp(Fightenv, 0); 1085 1.3 lukem /* NOTREACHED */ 1086 1.3 lukem 1087 1.3 lukem case 2: 1088 1.3 lukem addstr("It makes you invisible for you next monster.\n"); 1089 1.3 lukem getyx(stdscr, whichtreasure, ch); 1090 1.3 lukem more(whichtreasure); 1091 1.3 lukem Player.p_speed = 1e6; 1092 1.3 lukem Whichmonster = pickmonster(); 1093 1.3 lukem longjmp(Fightenv, 0); 1094 1.3 lukem /* NOTREACHED */ 1095 1.3 lukem 1096 1.3 lukem case 3: 1097 1.3 lukem addstr("It increases your strength ten fold to fight your next monster.\n"); 1098 1.3 lukem getyx(stdscr, whichtreasure, ch); 1099 1.3 lukem more(whichtreasure); 1100 1.3 lukem Player.p_might *= 10.0; 1101 1.3 lukem Whichmonster = pickmonster(); 1102 1.3 lukem longjmp(Fightenv, 0); 1103 1.3 lukem /* NOTREACHED */ 1104 1.3 lukem 1105 1.3 lukem case 4: 1106 1.3 lukem addstr("It is a general knowledge scroll.\n"); 1107 1.3 lukem Player.p_brains += ROLL(2.0, Circle); 1108 1.3 lukem Player.p_magiclvl += ROLL(1.0, Circle / 2.0); 1109 1.3 lukem break; 1110 1.3 lukem 1111 1.3 lukem case 5: 1112 1.3 lukem addstr("It tells you how to pick your next monster.\n"); 1113 1.3 lukem addstr("Which monster do you want [0-99] ? "); 1114 1.3 lukem Whichmonster = (int) infloat(); 1115 1.3 lukem Whichmonster = MIN(99, MAX(0, Whichmonster)); 1116 1.3 lukem longjmp(Fightenv, 0); 1117 1.3 lukem 1118 1.3 lukem case 6: 1119 1.3 lukem addstr("It was cursed!\n"); 1120 1.3 lukem cursedtreasure(); 1121 1.3 lukem break; 1122 1.3 lukem } 1123 1.3 lukem break; 1124 1.3 lukem /* end treasure type 4 */ 1125 1.1 jtc 1126 1.3 lukem case 5: /* treasure type 5 */ 1127 1.3 lukem switch (whichtreasure) { 1128 1.3 lukem case 1: 1129 1.3 lukem dtemp = ROLL(Circle / 4.0 + 5.0, Circle / 2.0 + 9.0); 1130 1.3 lukem printw("You've discovered a +%.0f dagger.\n", dtemp); 1131 1.3 lukem if (dtemp >= Player.p_sword) 1132 1.3 lukem Player.p_sword = dtemp; 1133 1.3 lukem else 1134 1.3 lukem SOMEBETTER(); 1135 1.3 lukem break; 1136 1.3 lukem 1137 1.3 lukem case 2: 1138 1.3 lukem dtemp = ROLL(7.5 + Circle * 3.0, Circle * 2.0 + 160.0); 1139 1.3 lukem printw("You have found some +%.0f armour!\n", dtemp); 1140 1.3 lukem if (dtemp >= Player.p_shield) 1141 1.3 lukem Player.p_shield = dtemp; 1142 1.3 lukem else 1143 1.3 lukem SOMEBETTER(); 1144 1.3 lukem break; 1145 1.3 lukem 1146 1.3 lukem case 3: 1147 1.3 lukem addstr("You've found a tablet.\n"); 1148 1.3 lukem Player.p_brains += 4.5 * Circle; 1149 1.3 lukem break; 1150 1.3 lukem } 1151 1.3 lukem break; 1152 1.3 lukem /* end treasure type 5 */ 1153 1.1 jtc 1154 1.3 lukem case 6: /* treasure type 6 */ 1155 1.3 lukem switch (whichtreasure) { 1156 1.3 lukem case 1: 1157 1.3 lukem addstr("You've found a priest.\n"); 1158 1.3 lukem Player.p_energy = Player.p_maxenergy + Player.p_shield; 1159 1.3 lukem Player.p_sin /= 2.0; 1160 1.3 lukem Player.p_mana += 24.0 * Circle; 1161 1.3 lukem Player.p_brains += Circle; 1162 1.3 lukem break; 1163 1.3 lukem 1164 1.3 lukem case 2: 1165 1.3 lukem addstr("You have come upon Robin Hood!\n"); 1166 1.3 lukem Player.p_shield += Circle * 2.0; 1167 1.3 lukem Player.p_strength += Circle / 2.5 + 1.0; 1168 1.3 lukem break; 1169 1.3 lukem 1170 1.3 lukem case 3: 1171 1.3 lukem dtemp = ROLL(2.0 + Circle / 4.0, Circle / 1.2 + 10.0); 1172 1.3 lukem printw("You have found a +%.0f axe!\n", dtemp); 1173 1.3 lukem if (dtemp >= Player.p_sword) 1174 1.3 lukem Player.p_sword = dtemp; 1175 1.3 lukem else 1176 1.3 lukem SOMEBETTER(); 1177 1.3 lukem break; 1178 1.3 lukem } 1179 1.3 lukem break; 1180 1.3 lukem /* end treasure type 6 */ 1181 1.1 jtc 1182 1.3 lukem case 7: /* treasure type 7 */ 1183 1.3 lukem switch (whichtreasure) { 1184 1.3 lukem case 1: 1185 1.3 lukem addstr("You've discovered a charm!\n"); 1186 1.3 lukem ++Player.p_charms; 1187 1.3 lukem break; 1188 1.3 lukem 1189 1.3 lukem case 2: 1190 1.3 lukem addstr("You have encountered Merlyn!\n"); 1191 1.3 lukem Player.p_brains += Circle + 5.0; 1192 1.3 lukem Player.p_magiclvl += Circle / 3.0 + 5.0; 1193 1.3 lukem Player.p_mana += Circle * 10.0; 1194 1.3 lukem break; 1195 1.3 lukem 1196 1.3 lukem case 3: 1197 1.3 lukem dtemp = ROLL(5.0 + Circle / 3.0, Circle / 1.5 + 20.0); 1198 1.3 lukem printw("You have found a +%.0f war hammer!\n", dtemp); 1199 1.3 lukem if (dtemp >= Player.p_sword) 1200 1.3 lukem Player.p_sword = dtemp; 1201 1.3 lukem else 1202 1.3 lukem SOMEBETTER(); 1203 1.3 lukem break; 1204 1.3 lukem } 1205 1.3 lukem break; 1206 1.3 lukem /* end treasure type 7 */ 1207 1.1 jtc 1208 1.3 lukem case 8: /* treasure type 8 */ 1209 1.3 lukem switch (whichtreasure) { 1210 1.3 lukem case 1: 1211 1.3 lukem addstr("You have found a healing potion.\n"); 1212 1.3 lukem Player.p_poison = MIN(-2.0, Player.p_poison - 2.0); 1213 1.3 lukem break; 1214 1.3 lukem 1215 1.3 lukem case 2: 1216 1.3 lukem addstr("You have discovered a transporter. Do you wish to go anywhere ? "); 1217 1.3 lukem ch = getanswer("NY", FALSE); 1218 1.3 lukem addstr("\n\n"); 1219 1.3 lukem if (ch == 'Y') { 1220 1.3 lukem double x, y; 1221 1.3 lukem 1222 1.3 lukem addstr("X Y Coordinates ? "); 1223 1.3 lukem getstring(Databuf, SZ_DATABUF); 1224 1.3 lukem sscanf(Databuf, "%lf %lf", &x, &y); 1225 1.3 lukem altercoordinates(x, y, A_FORCED); 1226 1.3 lukem } 1227 1.3 lukem break; 1228 1.3 lukem 1229 1.3 lukem case 3: 1230 1.3 lukem dtemp = ROLL(10.0 + Circle / 1.2, Circle * 3.0 + 30.0); 1231 1.3 lukem printw("You've found a +%.0f sword!\n", dtemp); 1232 1.3 lukem if (dtemp >= Player.p_sword) 1233 1.3 lukem Player.p_sword = dtemp; 1234 1.3 lukem else 1235 1.3 lukem SOMEBETTER(); 1236 1.3 lukem break; 1237 1.3 lukem } 1238 1.3 lukem break; 1239 1.3 lukem /* end treasure type 8 */ 1240 1.1 jtc 1241 1.3 lukem case 10: 1242 1.3 lukem case 11: 1243 1.3 lukem case 12: 1244 1.3 lukem case 13: /* treasure types 10 - 13 */ 1245 1.3 lukem if (drandom() < 0.33) { 1246 1.3 lukem if (Curmonster.m_treasuretype == 10) { 1247 1.3 lukem addstr("You've found a pair of elven boots!\n"); 1248 1.3 lukem Player.p_quickness += 2.0; 1249 1.3 lukem break; 1250 1.3 lukem } else 1251 1.3 lukem if (Curmonster.m_treasuretype == 11 1252 1.3 lukem && !Player.p_palantir) { 1253 1.3 lukem addstr("You've acquired Saruman's palantir.\n"); 1254 1.3 lukem Player.p_palantir = TRUE; 1255 1.3 lukem break; 1256 1.3 lukem } else 1257 1.3 lukem if (Player.p_ring.ring_type == R_NONE 1258 1.3 lukem && Player.p_specialtype < SC_COUNCIL 1259 1.3 lukem && (Curmonster.m_treasuretype == 12 1260 1.3 lukem || Curmonster.m_treasuretype == 13)) 1261 1.3 lukem /* roll 1262 1.3 lukem * up 1263 1.3 lukem * a 1264 1.3 lukem * ring 1265 1.3 lukem * */ 1266 1.3 lukem { 1267 1.3 lukem if (drandom() < 0.8) 1268 1.3 lukem /* r 1269 1.3 lukem * e 1270 1.3 lukem * g 1271 1.3 lukem * u 1272 1.3 lukem * l 1273 1.3 lukem * a 1274 1.3 lukem * r 1275 1.15 rillig * 1276 1.3 lukem * ri 1277 1.3 lukem * n 1278 1.3 lukem * g 1279 1.3 lukem * s 1280 1.3 lukem * */ 1281 1.3 lukem { 1282 1.3 lukem if (Curmonster.m_treasuretype == 12) { 1283 1.3 lukem whichtreasure = R_NAZREG; 1284 1.3 lukem temp = 35; 1285 1.3 lukem } else { 1286 1.3 lukem whichtreasure = R_DLREG; 1287 1.3 lukem temp = 0; 1288 1.3 lukem } 1289 1.3 lukem } else 1290 1.3 lukem /* b 1291 1.3 lukem * a 1292 1.3 lukem * d 1293 1.15 rillig * 1294 1.3 lukem * ri 1295 1.3 lukem * n 1296 1.3 lukem * g 1297 1.3 lukem * s 1298 1.3 lukem * */ 1299 1.3 lukem { 1300 1.3 lukem whichtreasure = R_BAD; 1301 1.3 lukem temp = 15 + Statptr->c_ringduration + (int) ROLL(0, 5); 1302 1.3 lukem } 1303 1.3 lukem 1304 1.3 lukem addstr("You've discovered a ring. Will you pick it up ? "); 1305 1.3 lukem ch = getanswer("NY", FALSE); 1306 1.3 lukem addstr("\n\n"); 1307 1.3 lukem 1308 1.3 lukem if (ch == 'Y') { 1309 1.3 lukem Player.p_ring.ring_type = whichtreasure; 1310 1.3 lukem Player.p_ring.ring_duration = temp; 1311 1.3 lukem } 1312 1.3 lukem break; 1313 1.3 lukem } 1314 1.1 jtc } 1315 1.3 lukem /* end treasure types 10 - 13 */ 1316 1.3 lukem /* fall through to treasure type 9 if 1317 1.3 lukem * no treasure from above */ 1318 1.3 lukem 1319 1.14 mrg /* FALLTHROUGH */ 1320 1.3 lukem case 9: /* treasure type 9 */ 1321 1.3 lukem switch (whichtreasure) { 1322 1.3 lukem case 1: 1323 1.3 lukem if (Player.p_level <= 1000.0 1324 1.3 lukem && Player.p_crowns <= 3 1325 1.3 lukem && Player.p_level >= 10.0) { 1326 1.3 lukem addstr("You have found a golden crown!\n"); 1327 1.3 lukem ++Player.p_crowns; 1328 1.3 lukem break; 1329 1.3 lukem } 1330 1.3 lukem 1331 1.14 mrg /* FALLTHROUGH */ 1332 1.3 lukem case 2: 1333 1.3 lukem addstr("You've been blessed!\n"); 1334 1.3 lukem Player.p_blessing = TRUE; 1335 1.3 lukem Player.p_sin /= 3.0; 1336 1.3 lukem Player.p_energy = Player.p_maxenergy + Player.p_shield; 1337 1.3 lukem Player.p_mana += 100.0 * Circle; 1338 1.3 lukem break; 1339 1.3 lukem 1340 1.3 lukem case 3: 1341 1.3 lukem dtemp = ROLL(1.0, Circle / 5.0 + 5.0); 1342 1.3 lukem dtemp = MIN(dtemp, 99.0); 1343 1.3 lukem printw("You have discovered some +%.0f quicksilver!\n", dtemp); 1344 1.3 lukem if (dtemp >= Player.p_quksilver) 1345 1.3 lukem Player.p_quksilver = dtemp; 1346 1.3 lukem else 1347 1.3 lukem SOMEBETTER(); 1348 1.3 lukem break; 1349 1.1 jtc } 1350 1.1 jtc break; 1351 1.3 lukem /* end treasure type 9 */ 1352 1.1 jtc } 1353 1.1 jtc } 1354 1.1 jtc } 1355 1.1 jtc 1356 1.12 dholland static void 1357 1.11 dholland cursedtreasure(void) 1358 1.1 jtc { 1359 1.3 lukem if (Player.p_charms > 0) { 1360 1.3 lukem addstr("But your charm saved you!\n"); 1361 1.3 lukem --Player.p_charms; 1362 1.3 lukem } else 1363 1.3 lukem if (Player.p_amulets > 0) { 1364 1.3 lukem addstr("But your amulet saved you!\n"); 1365 1.3 lukem --Player.p_amulets; 1366 1.3 lukem } else { 1367 1.3 lukem Player.p_energy = 1368 1.3 lukem (Player.p_maxenergy + Player.p_shield) / 10.0; 1369 1.3 lukem Player.p_poison += 0.25; 1370 1.3 lukem } 1371 1.1 jtc } 1372 1.1 jtc 1373 1.12 dholland static void 1374 1.11 dholland scramblestats(void) 1375 1.1 jtc { 1376 1.3 lukem double dbuf[6]; /* to put statistic in */ 1377 1.3 lukem double dtemp1, dtemp2; /* for swapping values */ 1378 1.3 lukem int first, second; /* indices for swapping */ 1379 1.3 lukem double *dptr; /* pointer for filling and emptying buf[] */ 1380 1.3 lukem 1381 1.3 lukem /* fill buffer */ 1382 1.3 lukem dptr = &dbuf[0]; 1383 1.3 lukem *dptr++ = Player.p_strength; 1384 1.3 lukem *dptr++ = Player.p_mana; 1385 1.3 lukem *dptr++ = Player.p_brains; 1386 1.3 lukem *dptr++ = Player.p_magiclvl; 1387 1.3 lukem *dptr++ = Player.p_energy; 1388 1.3 lukem *dptr = Player.p_sin; 1389 1.3 lukem 1390 1.3 lukem /* pick values to swap */ 1391 1.3 lukem first = (int) ROLL(0, 5); 1392 1.3 lukem second = (int) ROLL(0, 5); 1393 1.3 lukem 1394 1.3 lukem /* swap values */ 1395 1.3 lukem dptr = &dbuf[0]; 1396 1.3 lukem dtemp1 = dptr[first]; 1397 1.3 lukem /* this expression is split to prevent a compiler loop on some 1398 1.3 lukem * compilers */ 1399 1.3 lukem dtemp2 = dptr[second]; 1400 1.3 lukem dptr[first] = dtemp2; 1401 1.3 lukem dptr[second] = dtemp1; 1402 1.3 lukem 1403 1.3 lukem /* empty buffer */ 1404 1.3 lukem Player.p_strength = *dptr++; 1405 1.3 lukem Player.p_mana = *dptr++; 1406 1.3 lukem Player.p_brains = *dptr++; 1407 1.3 lukem Player.p_magiclvl = *dptr++; 1408 1.3 lukem Player.p_energy = *dptr++; 1409 1.3 lukem Player.p_sin = *dptr; 1410 1.1 jtc } 1411