Mercurial > hg > early-roguelike
comparison rogue4/weapons.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
| author | edwarj4 | 
|---|---|
| date | Sat, 24 Oct 2009 16:52:52 +0000 | 
| parents | |
| children | 1b73a8641b37 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 11:949d558c2162 | 12:9535a08ddc39 | 
|---|---|
| 1 /* | |
| 2 * Functions for dealing with problems brought about by weapons | |
| 3 * | |
| 4 * @(#)weapons.c 4.14 (Berkeley) 4/6/82 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman | |
| 8 * All rights reserved. | |
| 9 * | |
| 10 * See the file LICENSE.TXT for full copyright and licensing information. | |
| 11 */ | |
| 12 | |
| 13 #include <curses.h> | |
| 14 #include <ctype.h> | |
| 15 #include <string.h> | |
| 16 #include "rogue.h" | |
| 17 | |
| 18 #define NONE 100 | |
| 19 | |
| 20 static struct init_weps { | |
| 21 char *iw_dam; /* Damage when wielded */ | |
| 22 char *iw_hrl; /* Damage when thrown */ | |
| 23 char iw_launch; /* Launching weapon */ | |
| 24 int iw_flags; /* Miscellaneous flags */ | |
| 25 } init_dam[MAXWEAPONS] = { | |
| 26 "2d4", "1d3", NONE, 0, /* Mace */ | |
| 27 "3d4", "1d2", NONE, 0, /* Long sword */ | |
| 28 "1d1", "1d1", NONE, 0, /* Bow */ | |
| 29 "1d1", "2d3", BOW, ISMANY|ISMISL, /* Arrow */ | |
| 30 "1d6", "1d4", NONE, ISMISL, /* Dagger */ | |
| 31 "4d4", "1d2", NONE, 0, /* 2h sword */ | |
| 32 "1d1", "1d3", NONE, ISMANY|ISMISL, /* Dart */ | |
| 33 "1d1", "1d1", NONE, 0, /* Crossbow */ | |
| 34 "1d2", "2d5", CROSSBOW, ISMANY|ISMISL, /* Crossbow bolt */ | |
| 35 "2d3", "1d6", NONE, ISMISL, /* Spear */ | |
| 36 }; | |
| 37 | |
| 38 /* | |
| 39 * missile: | |
| 40 * Fire a missile in a given direction | |
| 41 */ | |
| 42 missile(ydelta, xdelta) | |
| 43 int ydelta, xdelta; | |
| 44 { | |
| 45 register THING *obj, *nitem; | |
| 46 | |
| 47 /* | |
| 48 * Get which thing we are hurling | |
| 49 */ | |
| 50 if ((obj = get_item("throw", WEAPON)) == NULL) | |
| 51 return; | |
| 52 if (!dropcheck(obj) || is_current(obj)) | |
| 53 return; | |
| 54 /* | |
| 55 * Get rid of the thing. If it is a non-multiple item object, or | |
| 56 * if it is the last thing, just drop it. Otherwise, create a new | |
| 57 * item with a count of one. | |
| 58 */ | |
| 59 if (obj->o_count < 2) | |
| 60 { | |
| 61 detach(pack, obj); | |
| 62 inpack--; | |
| 63 } | |
| 64 else | |
| 65 { | |
| 66 obj->o_count--; | |
| 67 if (obj->o_group == 0) | |
| 68 inpack--; | |
| 69 nitem = new_item(); | |
| 70 *nitem = *obj; | |
| 71 nitem->o_count = 1; | |
| 72 obj = nitem; | |
| 73 } | |
| 74 do_motion(obj, ydelta, xdelta); | |
| 75 /* | |
| 76 * AHA! Here it has hit something. If it is a wall or a door, | |
| 77 * or if it misses (combat) the monster, put it on the floor | |
| 78 */ | |
| 79 if (moat(obj->o_pos.y, obj->o_pos.x) == NULL | |
| 80 || !hit_monster(unc(obj->o_pos), obj)) | |
| 81 fall(obj, TRUE); | |
| 82 } | |
| 83 | |
| 84 /* | |
| 85 * do_motion: | |
| 86 * Do the actual motion on the screen done by an object traveling | |
| 87 * across the room | |
| 88 */ | |
| 89 do_motion(obj, ydelta, xdelta) | |
| 90 register THING *obj; | |
| 91 register int ydelta, xdelta; | |
| 92 { | |
| 93 /* | |
| 94 * Come fly with us ... | |
| 95 */ | |
| 96 obj->o_pos = hero; | |
| 97 for (;;) | |
| 98 { | |
| 99 register int ch; | |
| 100 | |
| 101 /* | |
| 102 * Erase the old one | |
| 103 */ | |
| 104 if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos))) | |
| 105 mvaddch(obj->o_pos.y, obj->o_pos.x, chat(obj->o_pos.y, obj->o_pos.x)); | |
| 106 /* | |
| 107 * Get the new position | |
| 108 */ | |
| 109 obj->o_pos.y += ydelta; | |
| 110 obj->o_pos.x += xdelta; | |
| 111 if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR) | |
| 112 { | |
| 113 /* | |
| 114 * It hasn't hit anything yet, so display it | |
| 115 * If it alright. | |
| 116 */ | |
| 117 if (cansee(unc(obj->o_pos))) | |
| 118 { | |
| 119 mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type); | |
| 120 refresh(); | |
| 121 } | |
| 122 continue; | |
| 123 } | |
| 124 break; | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 /* | |
| 129 * fall: | |
| 130 * Drop an item someplace around here. | |
| 131 */ | |
| 132 fall(obj, pr) | |
| 133 register THING *obj; | |
| 134 register bool pr; | |
| 135 { | |
| 136 static coord fpos; | |
| 137 register int index; | |
| 138 | |
| 139 if (fallpos(&obj->o_pos, &fpos, TRUE)) | |
| 140 { | |
| 141 index = INDEX(fpos.y, fpos.x); | |
| 142 _level[index] = obj->o_type; | |
| 143 obj->o_pos = fpos; | |
| 144 if (cansee(fpos.y, fpos.x)) | |
| 145 { | |
| 146 mvaddch(fpos.y, fpos.x, obj->o_type); | |
| 147 if (_monst[index] != NULL) | |
| 148 _monst[index]->t_oldch = obj->o_type; | |
| 149 } | |
| 150 attach(lvl_obj, obj); | |
| 151 return; | |
| 152 } | |
| 153 | |
| 154 if (pr) | |
| 155 msg("the %s vanishes as it hits the ground", | |
| 156 /* BUGFIX: Identification trick */ | |
| 157 (obj->o_type==WEAPON) ? w_names[obj->o_which] : inv_name(obj,TRUE)); | |
| 158 | |
| 159 discard(obj); | |
| 160 } | |
| 161 | |
| 162 /* | |
| 163 * init_weapon: | |
| 164 * Set up the initial goodies for a weapon | |
| 165 */ | |
| 166 init_weapon(weap, type) | |
| 167 register THING *weap; | |
| 168 char type; | |
| 169 { | |
| 170 register struct init_weps *iwp; | |
| 171 | |
| 172 iwp = &init_dam[type]; | |
| 173 strncpy(weap->o_damage, iwp->iw_dam, 8); | |
| 174 strncpy(weap->o_hurldmg, iwp->iw_hrl, 8); | |
| 175 weap->o_launch = iwp->iw_launch; | |
| 176 weap->o_flags = iwp->iw_flags; | |
| 177 if (weap->o_flags & ISMANY) | |
| 178 { | |
| 179 weap->o_count = rnd(8) + 8; | |
| 180 weap->o_group = group++; | |
| 181 } | |
| 182 else | |
| 183 weap->o_count = 1; | |
| 184 } | |
| 185 | |
| 186 /* | |
| 187 * hit_monster: | |
| 188 * Does the missile hit the monster? | |
| 189 */ | |
| 190 hit_monster(y, x, obj) | |
| 191 register int y, x; | |
| 192 THING *obj; | |
| 193 { | |
| 194 static coord mp; | |
| 195 | |
| 196 mp.y = y; | |
| 197 mp.x = x; | |
| 198 return fight(&mp, moat(y, x)->t_type, obj, TRUE); | |
| 199 } | |
| 200 | |
| 201 /* | |
| 202 * num: | |
| 203 * Figure out the plus number for armor/weapons | |
| 204 */ | |
| 205 char * | |
| 206 num(n1, n2, type) | |
| 207 register int n1, n2; | |
| 208 register char type; | |
| 209 { | |
| 210 static char numbuf[10]; | |
| 211 | |
| 212 sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1); | |
| 213 if (type == WEAPON) | |
| 214 sprintf(&numbuf[strlen(numbuf)], ",%s%d", n2 < 0 ? "" : "+", n2); | |
| 215 return numbuf; | |
| 216 } | |
| 217 | |
| 218 /* | |
| 219 * wield: | |
| 220 * Pull out a certain weapon | |
| 221 */ | |
| 222 wield() | |
| 223 { | |
| 224 register THING *obj, *oweapon; | |
| 225 register char *sp; | |
| 226 | |
| 227 oweapon = cur_weapon; | |
| 228 if (!dropcheck(cur_weapon)) | |
| 229 { | |
| 230 cur_weapon = oweapon; | |
| 231 return; | |
| 232 } | |
| 233 cur_weapon = oweapon; | |
| 234 if ((obj = get_item("wield", WEAPON)) == NULL) | |
| 235 { | |
| 236 bad: | |
| 237 after = FALSE; | |
| 238 return; | |
| 239 } | |
| 240 | |
| 241 if (obj->o_type == ARMOR) | |
| 242 { | |
| 243 msg("you can't wield armor"); | |
| 244 goto bad; | |
| 245 } | |
| 246 if (is_current(obj)) | |
| 247 goto bad; | |
| 248 | |
| 249 sp = inv_name(obj, TRUE); | |
| 250 cur_weapon = obj; | |
| 251 if (!terse) | |
| 252 addmsg("you are now "); | |
| 253 msg("wielding %s (%c)", sp, pack_char(obj)); | |
| 254 } | |
| 255 | |
| 256 /* | |
| 257 * fallpos: | |
| 258 * Pick a random position around the give (y, x) coordinates | |
| 259 */ | |
| 260 fallpos(pos, newpos, pass) | |
| 261 register coord *pos, *newpos; | |
| 262 register bool pass; | |
| 263 { | |
| 264 register int y, x, cnt, ch; | |
| 265 | |
| 266 cnt = 0; | |
| 267 for (y = pos->y - 1; y <= pos->y + 1; y++) | |
| 268 for (x = pos->x - 1; x <= pos->x + 1; x++) | |
| 269 { | |
| 270 /* | |
| 271 * check to make certain the spot is empty, if it is, | |
| 272 * put the object there, set it in the level list | |
| 273 * and re-draw the room if he can see it | |
| 274 */ | |
| 275 if (y == hero.y && x == hero.x) | |
| 276 continue; | |
| 277 if (((ch = chat(y, x)) == FLOOR || (pass && ch == PASSAGE)) | |
| 278 && rnd(++cnt) == 0) | |
| 279 { | |
| 280 newpos->y = y; | |
| 281 newpos->x = x; | |
| 282 } | |
| 283 } | |
| 284 return (cnt != 0); | |
| 285 } | 
