comparison rogue5/weapons.c @ 33:f502bf60e6e4

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