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