Mercurial > hg > early-roguelike
comparison rogue4/fight.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
| author | edwarj4 |
|---|---|
| date | Sat, 24 Oct 2009 16:52:52 +0000 |
| parents | |
| children | 1b73a8641b37 |
comparison
equal
deleted
inserted
replaced
| 11:949d558c2162 | 12:9535a08ddc39 |
|---|---|
| 1 /* | |
| 2 * All the fighting gets done here | |
| 3 * | |
| 4 * @(#)fight.c 4.30 (Berkeley) 4/6/82 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman | |
| 8 * All rights reserved. | |
| 9 * | |
| 10 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 11 */ | |
| 12 | |
| 13 #include <curses.h> | |
| 14 #include <ctype.h> | |
| 15 #include <string.h> | |
| 16 #include "rogue.h" | |
| 17 | |
| 18 long e_levels[] = { | |
| 19 10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L, | |
| 20 40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L | |
| 21 }; | |
| 22 | |
| 23 /* | |
| 24 * fight: | |
| 25 * The player attacks the monster. | |
| 26 */ | |
| 27 fight(mp, mn, weap, thrown) | |
| 28 register coord *mp; | |
| 29 char mn; | |
| 30 register THING *weap; | |
| 31 bool thrown; | |
| 32 { | |
| 33 register THING *tp; | |
| 34 register bool did_hit = TRUE; | |
| 35 register const char *mname; | |
| 36 | |
| 37 /* | |
| 38 * Find the monster we want to fight | |
| 39 */ | |
| 40 #ifdef WIZARD | |
| 41 if ((tp = moat(mp->y, mp->x)) == NULL) | |
| 42 debug("Fight what @ %d,%d", mp->y, mp->x); | |
| 43 #else | |
| 44 tp = moat(mp->y, mp->x); | |
| 45 #endif | |
| 46 /* | |
| 47 * Since we are fighting, things are not quiet so no healing takes | |
| 48 * place. | |
| 49 */ | |
| 50 count = quiet = 0; | |
| 51 runto(mp, &hero); | |
| 52 /* | |
| 53 * Let him know it was really a mimic (if it was one). | |
| 54 */ | |
| 55 if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND)) | |
| 56 { | |
| 57 tp->t_disguise = 'M'; | |
| 58 if (!thrown) | |
| 59 return FALSE; | |
| 60 msg("wait! That's a mimic!"); | |
| 61 } | |
| 62 did_hit = FALSE; | |
| 63 if (on(player, ISBLIND)) | |
| 64 mname = "it"; | |
| 65 else | |
| 66 mname = monsters[mn-'A'].m_name; | |
| 67 if (roll_em(&player, tp, weap, thrown)) | |
| 68 { | |
| 69 did_hit = FALSE; | |
| 70 if (thrown) | |
| 71 thunk(weap, mname); | |
| 72 else | |
| 73 hit(NULL, mname); | |
| 74 if (on(player, CANHUH)) | |
| 75 { | |
| 76 did_hit = TRUE; | |
| 77 tp->t_flags |= ISHUH; | |
| 78 player.t_flags &= ~CANHUH; | |
| 79 msg("your hands stop glowing red"); | |
| 80 } | |
| 81 if (tp->t_stats.s_hpt <= 0) | |
| 82 killed(tp, TRUE); | |
| 83 else if (did_hit && !on(player, ISBLIND)) | |
| 84 msg("the %s appears confused", mname); | |
| 85 did_hit = TRUE; | |
| 86 } | |
| 87 else | |
| 88 if (thrown) | |
| 89 bounce(weap, mname); | |
| 90 else | |
| 91 miss(NULL, mname); | |
| 92 return did_hit; | |
| 93 } | |
| 94 | |
| 95 /* | |
| 96 * attack: | |
| 97 * The monster attacks the player | |
| 98 */ | |
| 99 attack(mp) | |
| 100 register THING *mp; | |
| 101 { | |
| 102 register const char *mname; | |
| 103 | |
| 104 /* | |
| 105 * Since this is an attack, stop running and any healing that was | |
| 106 * going on at the time. | |
| 107 */ | |
| 108 running = FALSE; | |
| 109 count = quiet = 0; | |
| 110 if (mp->t_type == 'M' && !on(player, ISBLIND)) | |
| 111 mp->t_disguise = 'M'; | |
| 112 if (on(player, ISBLIND)) | |
| 113 mname = "it"; | |
| 114 else | |
| 115 mname = monsters[mp->t_type-'A'].m_name; | |
| 116 if (roll_em(mp, &player, NULL, FALSE)) | |
| 117 { | |
| 118 if (mp->t_type != 'E') | |
| 119 hit(mname, NULL); | |
| 120 if (pstats.s_hpt <= 0) | |
| 121 death(mp->t_type); /* Bye bye life ... */ | |
| 122 if (!on(*mp, ISCANC)) | |
| 123 switch (mp->t_type) | |
| 124 { | |
| 125 case 'R': | |
| 126 /* | |
| 127 * If a rust monster hits, you lose armor, unless | |
| 128 * that armor is leather or there is a magic ring | |
| 129 */ | |
| 130 if (cur_armor != NULL && cur_armor->o_ac < 9 | |
| 131 && cur_armor->o_which != LEATHER) | |
| 132 if (ISWEARING(R_SUSTARM)) | |
| 133 msg("The rust vanishes instantly"); | |
| 134 else | |
| 135 { | |
| 136 cur_armor->o_ac++; | |
| 137 if (!terse) | |
| 138 msg("your armor appears to be weaker now. Oh my!"); | |
| 139 else | |
| 140 msg("your armor weakens"); | |
| 141 } | |
| 142 when 'E': | |
| 143 /* | |
| 144 * The gaze of the floating eye hypnotizes you | |
| 145 */ | |
| 146 if (on(player, ISBLIND)) | |
| 147 break; | |
| 148 player.t_flags &= ~ISRUN; | |
| 149 if (!no_command) | |
| 150 { | |
| 151 addmsg("you are transfixed"); | |
| 152 if (!terse) | |
| 153 addmsg(" by the gaze of the floating eye"); | |
| 154 endmsg(); | |
| 155 } | |
| 156 no_command += rnd(2) + 2; | |
| 157 when 'A': | |
| 158 /* | |
| 159 * Ants have poisonous bites | |
| 160 */ | |
| 161 if (!save(VS_POISON)) | |
| 162 if (!ISWEARING(R_SUSTSTR)) | |
| 163 { | |
| 164 chg_str(-1); | |
| 165 if (!terse) | |
| 166 msg("you feel a sting in your arm and now feel weaker"); | |
| 167 else | |
| 168 msg("a sting has weakened you"); | |
| 169 } | |
| 170 else | |
| 171 if (!terse) | |
| 172 msg("a sting momentarily weakens you"); | |
| 173 else | |
| 174 msg("sting has no effect"); | |
| 175 when 'W': | |
| 176 case 'V': | |
| 177 /* | |
| 178 * Wraiths might drain energy levels, and Vampires | |
| 179 * can steal max_hp | |
| 180 */ | |
| 181 if (rnd(100) < (mp->t_type == 'W' ? 15 : 30)) | |
| 182 { | |
| 183 register int fewer; | |
| 184 | |
| 185 if (mp->t_type == 'W') | |
| 186 { | |
| 187 if (pstats.s_exp == 0) | |
| 188 death('W'); /* All levels gone */ | |
| 189 if (--pstats.s_lvl == 0) | |
| 190 { | |
| 191 pstats.s_exp = 0; | |
| 192 pstats.s_lvl = 1; | |
| 193 } | |
| 194 else | |
| 195 pstats.s_exp = e_levels[pstats.s_lvl-1]+1; | |
| 196 fewer = roll(1, 10); | |
| 197 } | |
| 198 else | |
| 199 fewer = roll(1, 5); | |
| 200 pstats.s_hpt -= fewer; | |
| 201 max_hp -= fewer; | |
| 202 if (pstats.s_hpt < 1) | |
| 203 pstats.s_hpt = 1; | |
| 204 if (max_hp < 1) | |
| 205 death(mp->t_type); | |
| 206 msg("you suddenly feel weaker"); | |
| 207 } | |
| 208 when 'F': | |
| 209 /* | |
| 210 * Violet fungi stops the poor guy from moving | |
| 211 */ | |
| 212 player.t_flags |= ISHELD; | |
| 213 sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit); | |
| 214 when 'L': | |
| 215 { | |
| 216 /* | |
| 217 * Leperachaun steals some gold | |
| 218 */ | |
| 219 register long lastpurse; | |
| 220 | |
| 221 lastpurse = purse; | |
| 222 purse -= GOLDCALC; | |
| 223 if (!save(VS_MAGIC)) | |
| 224 purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC; | |
| 225 if (purse < 0) | |
| 226 purse = 0; | |
| 227 remove_monster(&mp->t_pos, mp, FALSE); | |
| 228 mp = NULL; | |
| 229 if (purse != lastpurse) | |
| 230 msg("your purse feels lighter"); | |
| 231 } | |
| 232 when 'N': | |
| 233 { | |
| 234 register THING *obj, *steal; | |
| 235 register int nobj; | |
| 236 | |
| 237 /* | |
| 238 * Nymph's steal a magic item, look through the pack | |
| 239 * and pick out one we like. | |
| 240 */ | |
| 241 steal = NULL; | |
| 242 for (nobj = 0, obj = pack; obj != NULL; obj = next(obj)) | |
| 243 if (obj != cur_armor && obj != cur_weapon | |
| 244 && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT] | |
| 245 && is_magic(obj) && rnd(++nobj) == 0) | |
| 246 steal = obj; | |
| 247 if (steal != NULL) | |
| 248 { | |
| 249 remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE); | |
| 250 mp = NULL; | |
| 251 inpack--; | |
| 252 if (steal->o_count > 1 && steal->o_group == 0) | |
| 253 { | |
| 254 register int oc; | |
| 255 | |
| 256 oc = steal->o_count--; | |
| 257 steal->o_count = 1; | |
| 258 msg("she stole %s!", inv_name(steal, TRUE)); | |
| 259 steal->o_count = oc; | |
| 260 } | |
| 261 else | |
| 262 { | |
| 263 detach(pack, steal); | |
| 264 msg("she stole %s!", inv_name(steal, TRUE)); | |
| 265 discard(steal); | |
| 266 } | |
| 267 } | |
| 268 } | |
| 269 otherwise: | |
| 270 break; | |
| 271 } | |
| 272 } | |
| 273 else if (mp->t_type != 'E') | |
| 274 { | |
| 275 if (mp->t_type == 'F') | |
| 276 { | |
| 277 pstats.s_hpt -= fung_hit; | |
| 278 if (pstats.s_hpt <= 0) | |
| 279 death(mp->t_type); /* Bye bye life ... */ | |
| 280 } | |
| 281 miss(mname, NULL); | |
| 282 } | |
| 283 if (fight_flush) | |
| 284 flush_type(); | |
| 285 count = 0; | |
| 286 status(); | |
| 287 | |
| 288 if (mp == NULL) | |
| 289 return(-1); | |
| 290 else | |
| 291 return(0); | |
| 292 } | |
| 293 | |
| 294 /* | |
| 295 * swing: | |
| 296 * Returns true if the swing hits | |
| 297 */ | |
| 298 swing(at_lvl, op_arm, wplus) | |
| 299 int at_lvl, op_arm, wplus; | |
| 300 { | |
| 301 register int res = rnd(20); | |
| 302 register int need = (20 - at_lvl) - op_arm; | |
| 303 | |
| 304 return (res + wplus >= need); | |
| 305 } | |
| 306 | |
| 307 /* | |
| 308 * check_level: | |
| 309 * Check to see if the guy has gone up a level. | |
| 310 */ | |
| 311 check_level() | |
| 312 { | |
| 313 register int i, add, olevel; | |
| 314 | |
| 315 for (i = 0; e_levels[i] != 0; i++) | |
| 316 if (e_levels[i] > pstats.s_exp) | |
| 317 break; | |
| 318 i++; | |
| 319 olevel = pstats.s_lvl; | |
| 320 pstats.s_lvl = i; | |
| 321 if (i > olevel) | |
| 322 { | |
| 323 add = roll(i - olevel, 10); | |
| 324 max_hp += add; | |
| 325 if ((pstats.s_hpt += add) > max_hp) | |
| 326 pstats.s_hpt = max_hp; | |
| 327 msg("welcome to level %d", i); | |
| 328 } | |
| 329 } | |
| 330 | |
| 331 /* | |
| 332 * roll_em: | |
| 333 * Roll several attacks | |
| 334 */ | |
| 335 roll_em(thatt, thdef, weap, hurl) | |
| 336 THING *thatt, *thdef, *weap; | |
| 337 bool hurl; | |
| 338 { | |
| 339 register struct stats *att, *def; | |
| 340 register char *cp; | |
| 341 register int ndice, nsides, def_arm; | |
| 342 register bool did_hit = FALSE; | |
| 343 register int hplus; | |
| 344 register int dplus; | |
| 345 register int damage; | |
| 346 | |
| 347 att = &thatt->t_stats; | |
| 348 def = &thdef->t_stats; | |
| 349 if (weap == NULL) | |
| 350 { | |
| 351 cp = att->s_dmg; | |
| 352 dplus = 0; | |
| 353 hplus = 0; | |
| 354 } | |
| 355 else | |
| 356 { | |
| 357 hplus = (weap == NULL ? 0 : weap->o_hplus); | |
| 358 dplus = (weap == NULL ? 0 : weap->o_dplus); | |
| 359 if (weap == cur_weapon) | |
| 360 { | |
| 361 if (ISRING(LEFT, R_ADDDAM)) | |
| 362 dplus += cur_ring[LEFT]->o_ac; | |
| 363 else if (ISRING(LEFT, R_ADDHIT)) | |
| 364 hplus += cur_ring[LEFT]->o_ac; | |
| 365 if (ISRING(RIGHT, R_ADDDAM)) | |
| 366 dplus += cur_ring[RIGHT]->o_ac; | |
| 367 else if (ISRING(RIGHT, R_ADDHIT)) | |
| 368 hplus += cur_ring[RIGHT]->o_ac; | |
| 369 } | |
| 370 if (hurl) | |
| 371 if ((weap->o_flags&ISMISL) && cur_weapon != NULL && | |
| 372 cur_weapon->o_which == weap->o_launch) | |
| 373 { | |
| 374 cp = weap->o_hurldmg; | |
| 375 hplus += cur_weapon->o_hplus; | |
| 376 dplus += cur_weapon->o_dplus; | |
| 377 } | |
| 378 else | |
| 379 cp = weap->o_hurldmg; | |
| 380 else | |
| 381 { | |
| 382 cp = weap->o_damage; | |
