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