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