1 /* 2 * Copyright (c) 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Timothy C. Stoehr. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)throw.c 8.1 (Berkeley) 05/31/93"; 13 #endif /* not lint */ 14 15 /* 16 * throw.c 17 * 18 * This source herein may be modified and/or distributed by anybody who 19 * so desires, with the following restrictions: 20 * 1.) No portion of this notice shall be removed. 21 * 2.) Credit shall not be taken for the creation of this source. 22 * 3.) This code is not to be traded, sold, or used for personal 23 * gain or profit. 24 * 25 */ 26 27 #include "rogue.h" 28 29 extern short cur_room; 30 extern char *curse_message; 31 extern char hit_message[]; 32 33 throw() 34 { 35 short wch, d; 36 boolean first_miss = 1; 37 object *weapon; 38 short dir, row, col; 39 object *monster; 40 41 while (!is_direction(dir = rgetchar(), &d)) { 42 sound_bell(); 43 if (first_miss) { 44 message("direction? ", 0); 45 first_miss = 0; 46 } 47 } 48 check_message(); 49 if (dir == CANCEL) { 50 return; 51 } 52 if ((wch = pack_letter("throw what?", WEAPON)) == CANCEL) { 53 return; 54 } 55 check_message(); 56 57 if (!(weapon = get_letter_object(wch))) { 58 message("no such item.", 0); 59 return; 60 } 61 if ((weapon->in_use_flags & BEING_USED) && weapon->is_cursed) { 62 message(curse_message, 0); 63 return; 64 } 65 row = rogue.row; col = rogue.col; 66 67 if ((weapon->in_use_flags & BEING_WIELDED) && (weapon->quantity <= 1)) { 68 unwield(rogue.weapon); 69 } else if (weapon->in_use_flags & BEING_WORN) { 70 mv_aquatars(); 71 unwear(rogue.armor); 72 print_stats(STAT_ARMOR); 73 } else if (weapon->in_use_flags & ON_EITHER_HAND) { 74 un_put_on(weapon); 75 } 76 monster = get_thrown_at_monster(weapon, d, &row, &col); 77 mvaddch(rogue.row, rogue.col, rogue.fchar); 78 refresh(); 79 80 if (rogue_can_see(row, col) && ((row != rogue.row) || (col != rogue.col))){ 81 mvaddch(row, col, get_dungeon_char(row, col)); 82 } 83 if (monster) { 84 wake_up(monster); 85 check_gold_seeker(monster); 86 87 if (!throw_at_monster(monster, weapon)) { 88 flop_weapon(weapon, row, col); 89 } 90 } else { 91 flop_weapon(weapon, row, col); 92 } 93 vanish(weapon, 1, &rogue.pack); 94 } 95 96 throw_at_monster(monster, weapon) 97 object *monster, *weapon; 98 { 99 short damage, hit_chance; 100 short t; 101 102 hit_chance = get_hit_chance(weapon); 103 damage = get_weapon_damage(weapon); 104 if ((weapon->which_kind == ARROW) && 105 (rogue.weapon && (rogue.weapon->which_kind == BOW))) { 106 damage += get_weapon_damage(rogue.weapon); 107 damage = ((damage * 2) / 3); 108 hit_chance += (hit_chance / 3); 109 } else if ((weapon->in_use_flags & BEING_WIELDED) && 110 ((weapon->which_kind == DAGGER) || 111 (weapon->which_kind == SHURIKEN) || 112 (weapon->which_kind == DART))) { 113 damage = ((damage * 3) / 2); 114 hit_chance += (hit_chance / 3); 115 } 116 t = weapon->quantity; 117 weapon->quantity = 1; 118 sprintf(hit_message, "the %s", name_of(weapon)); 119 weapon->quantity = t; 120 121 if (!rand_percent(hit_chance)) { 122 (void) strcat(hit_message, "misses "); 123 return(0); 124 } 125 s_con_mon(monster); 126 (void) strcat(hit_message, "hit "); 127 (void) mon_damage(monster, damage); 128 return(1); 129 } 130 131 object * 132 get_thrown_at_monster(obj, dir, row, col) 133 object *obj; 134 short dir; 135 short *row, *col; 136 { 137 short orow, ocol; 138 short i, ch; 139 140 orow = *row; ocol = *col; 141 142 ch = get_mask_char(obj->what_is); 143 144 for (i = 0; i < 24; i++) { 145 get_dir_rc(dir, row, col, 0); 146 if ( (((*col <= 0) || (*col >= DCOLS-1)) || 147 (dungeon[*row][*col] == NOTHING)) || 148 ((dungeon[*row][*col] & (HORWALL | VERTWALL | HIDDEN)) && 149 (!(dungeon[*row][*col] & TRAP)))) { 150 *row = orow; 151 *col = ocol; 152 return(0); 153 } 154 if ((i != 0) && rogue_can_see(orow, ocol)) { 155 mvaddch(orow, ocol, get_dungeon_char(orow, ocol)); 156 } 157 if (rogue_can_see(*row, *col)) { 158 if (!(dungeon[*row][*col] & MONSTER)) { 159 mvaddch(*row, *col, ch); 160 } 161 refresh(); 162 } 163 orow = *row; ocol = *col; 164 if (dungeon[*row][*col] & MONSTER) { 165 if (!imitating(*row, *col)) { 166 return(object_at(&level_monsters, *row, *col)); 167 } 168 } 169 if (dungeon[*row][*col] & TUNNEL) { 170 i += 2; 171 } 172 } 173 return(0); 174 } 175 176 flop_weapon(weapon, row, col) 177 object *weapon; 178 short row, col; 179 { 180 object *new_weapon, *monster; 181 short i = 0; 182 char msg[80]; 183 boolean found = 0; 184 short mch, dch; 185 unsigned short mon; 186 187 while ((i < 9) && dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER)) { 188 rand_around(i++, &row, &col); 189 if ((row > (DROWS-2)) || (row < MIN_ROW) || 190 (col > (DCOLS-1)) || (col < 0) || (!dungeon[row][col]) || 191 (dungeon[row][col] & ~(FLOOR | TUNNEL | DOOR | MONSTER))) { 192 continue; 193 } 194 found = 1; 195 break; 196 } 197 198 if (found || (i == 0)) { 199 new_weapon = alloc_object(); 200 *new_weapon = *weapon; 201 new_weapon->in_use_flags = NOT_USED; 202 new_weapon->quantity = 1; 203 new_weapon->ichar = 'L'; 204 place_at(new_weapon, row, col); 205 if (rogue_can_see(row, col) && 206 ((row != rogue.row) || (col != rogue.col))) { 207 mon = dungeon[row][col] & MONSTER; 208 dungeon[row][col] &= (~MONSTER); 209 dch = get_dungeon_char(row, col); 210 if (mon) { 211 mch = mvinch(row, col); 212 if (monster = object_at(&level_monsters, row, col)) { 213 monster->trail_char = dch; 214 } 215 if ((mch < 'A') || (mch > 'Z')) { 216 mvaddch(row, col, dch); 217 } 218 } else { 219 mvaddch(row, col, dch); 220 } 221 dungeon[row][col] |= mon; 222 } 223 } else { 224 short t; 225 226 t = weapon->quantity; 227 weapon->quantity = 1; 228 sprintf(msg, "the %svanishes as it hits the ground", 229 name_of(weapon)); 230 weapon->quantity = t; 231 message(msg, 0); 232 } 233 } 234 235 rand_around(i, r, c) 236 short i, *r, *c; 237 { 238 static char* pos = "\010\007\001\003\004\005\002\006\0"; 239 static short row, col; 240 short j; 241 242 if (i == 0) { 243 short x, y, o, t; 244 245 row = *r; 246 col = *c; 247 248 o = get_rand(1, 8); 249 250 for (j = 0; j < 5; j++) { 251 x = get_rand(0, 8); 252 y = (x + o) % 9; 253 t = pos[x]; 254 pos[x] = pos[y]; 255 pos[y] = t; 256 } 257 } 258 switch((short)pos[i]) { 259 case 0: 260 *r = row + 1; 261 *c = col + 1; 262 break; 263 case 1: 264 *r = row + 1; 265 *c = col - 1; 266 break; 267 case 2: 268 *r = row - 1; 269 *c = col + 1; 270 break; 271 case 3: 272 *r = row - 1; 273 *c = col - 1; 274 break; 275 case 4: 276 *r = row; 277 *c = col + 1; 278 break; 279 case 5: 280 *r = row + 1; 281 *c = col; 282 break; 283 case 6: 284 *r = row; 285 *c = col; 286 break; 287 case 7: 288 *r = row - 1; 289 *c = col; 290 break; 291 case 8: 292 *r = row; 293 *c = col - 1; 294 break; 295 } 296 } 297