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