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