1: /* 2: * hit.c 3: * 4: * This source herein may be modified and/or distributed by anybody who 5: * so desires, with the following restrictions: 6: * 1.) No portion of this notice shall be removed. 7: * 2.) Credit shall not be taken for the creation of this source. 8: * 3.) This code is not to be traded, sold, or used for personal 9: * gain or profit. 10: * 11: */ 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)hit.c 5.1 (Berkeley) 11/25/87"; 15: #endif /* not lint */ 16: 17: #include "rogue.h" 18: 19: object *fight_monster = 0; 20: char hit_message[80] = ""; 21: 22: extern short halluc, blind, cur_level; 23: extern short add_strength, ring_exp, r_rings; 24: extern boolean being_held, interrupted, wizard, con_mon; 25: 26: mon_hit(monster) 27: register object *monster; 28: { 29: short damage, hit_chance; 30: char *mn; 31: float minus; 32: 33: if (fight_monster && (monster != fight_monster)) { 34: fight_monster = 0; 35: } 36: monster->trow = NO_ROOM; 37: if (cur_level >= (AMULET_LEVEL * 2)) { 38: hit_chance = 100; 39: } else { 40: hit_chance = monster->m_hit_chance; 41: hit_chance -= (((2 * rogue.exp) + (2 * ring_exp)) - r_rings); 42: } 43: if (wizard) { 44: hit_chance /= 2; 45: } 46: if (!fight_monster) { 47: interrupted = 1; 48: } 49: mn = mon_name(monster); 50: 51: if (!rand_percent(hit_chance)) { 52: if (!fight_monster) { 53: sprintf(hit_message + strlen(hit_message), "the %s misses", mn); 54: message(hit_message, 1); 55: hit_message[0] = 0; 56: } 57: return; 58: } 59: if (!fight_monster) { 60: sprintf(hit_message + strlen(hit_message), "the %s hit", mn); 61: message(hit_message, 1); 62: hit_message[0] = 0; 63: } 64: if (!(monster->m_flags & STATIONARY)) { 65: damage = get_damage(monster->m_damage, 1); 66: if (cur_level >= (AMULET_LEVEL * 2)) { 67: minus = (float) ((AMULET_LEVEL * 2) - cur_level); 68: } else { 69: minus = (float) get_armor_class(rogue.armor) * 3.00; 70: minus = minus/100.00 * (float) damage; 71: } 72: damage -= (short) minus; 73: } else { 74: damage = monster->stationary_damage++; 75: } 76: if (wizard) { 77: damage /= 3; 78: } 79: if (damage > 0) { 80: rogue_damage(damage, monster, 0); 81: } 82: if (monster->m_flags & SPECIAL_HIT) { 83: special_hit(monster); 84: } 85: } 86: 87: rogue_hit(monster, force_hit) 88: register object *monster; 89: boolean force_hit; 90: { 91: short damage, hit_chance; 92: 93: if (monster) { 94: if (check_imitator(monster)) { 95: return; 96: } 97: hit_chance = force_hit ? 100 : get_hit_chance(rogue.weapon); 98: 99: if (wizard) { 100: hit_chance *= 2; 101: } 102: if (!rand_percent(hit_chance)) { 103: if (!fight_monster) { 104: (void) strcpy(hit_message, "you miss "); 105: } 106: goto RET; 107: } 108: damage = get_weapon_damage(rogue.weapon); 109: if (wizard) { 110: damage *= 3; 111: } 112: if (con_mon) { 113: s_con_mon(monster); 114: } 115: if (mon_damage(monster, damage)) { /* still alive? */ 116: if (!fight_monster) { 117: (void) strcpy(hit_message, "you hit "); 118: } 119: } 120: RET: check_gold_seeker(monster); 121: wake_up(monster); 122: } 123: } 124: 125: rogue_damage(d, monster, other) 126: short d; 127: object *monster; 128: short other; 129: { 130: if (d >= rogue.hp_current) { 131: rogue.hp_current = 0; 132: print_stats(STAT_HP); 133: killed_by(monster, other); 134: } 135: if (d > 0) { 136: rogue.hp_current -= d; 137: print_stats(STAT_HP); 138: } 139: } 140: 141: get_damage(ds, r) 142: char *ds; 143: boolean r; 144: { 145: register i = 0, j, n, d, total = 0; 146: 147: while (ds[i]) { 148: n = get_number(ds+i); 149: while (ds[i++] != 'd') ; 150: d = get_number(ds+i); 151: while ((ds[i] != '/') && ds[i]) i++; 152: 153: for (j = 0; j < n; j++) { 154: if (r) { 155: total += get_rand(1, d); 156: } else { 157: total += d; 158: } 159: } 160: if (ds[i] == '/') { 161: i++; 162: } 163: } 164: return(total); 165: } 166: 167: get_w_damage(obj) 168: object *obj; 169: { 170: char new_damage[12]; 171: register to_hit, damage; 172: register i = 0; 173: 174: if ((!obj) || (obj->what_is != WEAPON)) { 175: return(-1); 176: } 177: to_hit = get_number(obj->damage) + obj->hit_enchant; 178: while (obj->damage[i++] != 'd') ; 179: damage = get_number(obj->damage + i) + obj->d_enchant; 180: 181: sprintf(new_damage, "%dd%d", to_hit, damage); 182: 183: return(get_damage(new_damage, 1)); 184: } 185: 186: get_number(s) 187: register char *s; 188: { 189: register i = 0; 190: register total = 0; 191: 192: while ((s[i] >= '0') && (s[i] <= '9')) { 193: total = (10 * total) + (s[i] - '0'); 194: i++; 195: } 196: return(total); 197: } 198: 199: long 200: lget_number(s) 201: char *s; 202: { 203: short i = 0; 204: long total = 0; 205: 206: while ((s[i] >= '0') && (s[i] <= '9')) { 207: total = (10 * total) + (s[i] - '0'); 208: i++; 209: } 210: return(total); 211: } 212: 213: to_hit(obj) 214: object *obj; 215: { 216: if (!obj) { 217: return(1); 218: } 219: return(get_number(obj->damage) + obj->hit_enchant); 220: } 221: 222: damage_for_strength() 223: { 224: short strength; 225: 226: strength = rogue.str_current + add_strength; 227: 228: if (strength <= 6) { 229: return(strength-5); 230: } 231: if (strength <= 14) { 232: return(1); 233: } 234: if (strength <= 17) { 235: return(3); 236: } 237: if (strength <= 18) { 238: return(4); 239: } 240: if (strength <= 20) { 241: return(5); 242: } 243: if (strength <= 21) { 244: return(6); 245: } 246: if (strength <= 30) { 247: return(7); 248: } 249: return(8); 250: } 251: 252: mon_damage(monster, damage) 253: object *monster; 254: short damage; 255: { 256: char *mn; 257: short row, col; 258: 259: monster->hp_to_kill -= damage; 260: 261: if (monster->hp_to_kill <= 0) { 262: row = monster->row; 263: col = monster->col; 264: dungeon[row][col] &= ~MONSTER; 265: mvaddch(row, col, (int) get_dungeon_char(row, col)); 266: 267: fight_monster = 0; 268: cough_up(monster); 269: mn = mon_name(monster); 270: sprintf(hit_message+strlen(hit_message), "defeated the %s", mn); 271: message(hit_message, 1); 272: hit_message[0] = 0; 273: add_exp(monster->kill_exp, 1); 274: take_from_pack(monster, &level_monsters); 275: 276: if (monster->m_flags & HOLDS) { 277: being_held = 0; 278: } 279: free_object(monster); 280: return(0); 281: } 282: return(1); 283: } 284: 285: fight(to_the_death) 286: boolean to_the_death; 287: { 288: short ch, c, d; 289: short row, col; 290: boolean first_miss = 1; 291: short possible_damage; 292: object *monster; 293: 294: while (!is_direction(ch = rgetchar(), &d)) { 295: sound_bell(); 296: if (first_miss) { 297: message("direction?", 0); 298: first_miss = 0; 299: } 300: } 301: check_message(); 302: if (ch == CANCEL) { 303: return; 304: } 305: row = rogue.row; col = rogue.col; 306: get_dir_rc(d, &row, &col, 0); 307: 308: c = mvinch(row, col); 309: if (((c < 'A') || (c > 'Z')) || 310: (!can_move(rogue.row, rogue.col, row, col))) { 311: message("I see no monster there", 0); 312: return; 313: } 314: if (!(fight_monster = object_at(&level_monsters, row, col))) { 315: return; 316: } 317: if (!(fight_monster->m_flags & STATIONARY)) { 318: possible_damage = ((get_damage(fight_monster->m_damage, 0) * 2) / 3); 319: } else { 320: possible_damage = fight_monster->stationary_damage - 1; 321: } 322: while (fight_monster) { 323: (void) one_move_rogue(ch, 0); 324: if (((!to_the_death) && (rogue.hp_current <= possible_damage)) || 325: interrupted || (!(dungeon[row][col] & MONSTER))) { 326: fight_monster = 0; 327: } else { 328: monster = object_at(&level_monsters, row, col); 329: if (monster != fight_monster) { 330: fight_monster = 0; 331: } 332: } 333: } 334: } 335: 336: get_dir_rc(dir, row, col, allow_off_screen) 337: short dir; 338: short *row, *col; 339: short allow_off_screen; 340: { 341: switch(dir) { 342: case LEFT: 343: if (allow_off_screen || (*col > 0)) { 344: (*col)--; 345: } 346: break; 347: case DOWN: 348: if (allow_off_screen || (*row < (DROWS-2))) { 349: (*row)++; 350: } 351: break; 352: case UPWARD: 353: if (allow_off_screen || (*row > MIN_ROW)) { 354: (*row)--; 355: } 356: break; 357: case RIGHT: 358: if (allow_off_screen || (*col < (DCOLS-1))) { 359: (*col)++; 360: } 361: break; 362: case UPLEFT: 363: if (allow_off_screen || ((*row > MIN_ROW) && (*col > 0))) { 364: (*row)--; 365: (*col)--; 366: } 367: break; 368: case UPRIGHT: 369: if (allow_off_screen || ((*row > MIN_ROW) && (*col < (DCOLS-1)))) { 370: (*row)--; 371: (*col)++; 372: } 373: break; 374: case DOWNRIGHT: 375: if (allow_off_screen || ((*row < (DROWS-2)) && (*col < (DCOLS-1)))) { 376: (*row)++; 377: (*col)++; 378: } 379: break; 380: case DOWNLEFT: 381: if (allow_off_screen || ((*row < (DROWS-2)) && (*col > 0))) { 382: (*row)++; 383: (*col)--; 384: } 385: break; 386: } 387: } 388: 389: get_hit_chance(weapon) 390: object *weapon; 391: { 392: short hit_chance; 393: 394: hit_chance = 40; 395: hit_chance += 3 * to_hit(weapon); 396: hit_chance += (((2 * rogue.exp) + (2 * ring_exp)) - r_rings); 397: return(hit_chance); 398: } 399: 400: get_weapon_damage(weapon) 401: object *weapon; 402: { 403: short damage; 404: 405: damage = get_w_damage(weapon); 406: damage += damage_for_strength(); 407: damage += ((((rogue.exp + ring_exp) - r_rings) + 1) / 2); 408: return(damage); 409: } 410: 411: s_con_mon(monster) 412: object *monster; 413: { 414: if (con_mon) { 415: monster->m_flags |= CONFUSED; 416: monster->moves_confused += get_rand(12, 22); 417: message("the monster appears confused", 0); 418: con_mon = 0; 419: } 420: }