Annotation of early-roguelike/arogue7/weapons.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * weapons.c - Functions for dealing with problems brought about by weapons
3: *
4: * Advanced Rogue
5: * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
6: * All rights reserved.
7: *
8: * Based on "Rogue: Exploring the Dungeons of Doom"
9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
10: * All rights reserved.
11: *
12: * See the file LICENSE.TXT for full copyright and licensing information.
13: */
14:
15: /*
16: * Functions for dealing with problems brought about by weapons
17: *
18: */
19:
20: #include "curses.h"
21: #include <ctype.h>
22: #include <string.h>
23: #include "rogue.h"
24:
25: void
26: boomerang(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
27: {
28: register struct object *obj;
29: struct thing midpoint;
30: coord oldpos;
31:
32: obj = OBJPTR(item);
33: oldpos = obj->o_pos;
34:
35: /*
36: * make it appear to fly at the target
37: */
38: do_motion(obj, ydelta, xdelta, tp);
39: hit_monster(unc(obj->o_pos), obj, tp);
40:
41: /*
42: * Now let's make it fly back to the wielder. We need to
43: * use midpoint to fool do_motion into thinking the action
44: * starts there. Do_motion only looks at the t_pos field.
45: */
46: midpoint.t_pos = obj->o_pos; /* Simulate a new start position */
47: do_motion(obj, -ydelta, -xdelta, &midpoint);
48:
49: obj->o_pos = oldpos;
50: }
51:
52: /*
53: * do the actual motion on the screen done by an object traveling
54: * across the room. Note that we should not look at any field in
55: * tp other than t_pos unless we change boomerang().
56: */
57: void
58: do_motion(struct object *obj, int ydelta, int xdelta, struct thing *tp)
59: {
60:
61: /*
62: * Come fly with us ...
63: */
64: obj->o_pos = tp->t_pos;
65: for (; ;) {
66: register int ch;
67: /*
68: * Erase the old one
69: */
70: if (!ce(obj->o_pos, tp->t_pos) &&
71: cansee(unc(obj->o_pos)) &&
72: mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
73: mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x));
74: }
75: /*
76: * Get the new position
77: */
78: obj->o_pos.y += ydelta;
79: obj->o_pos.x += xdelta;
80: if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
81: /*
82: * It hasn't hit anything yet, so display it
83: * If it alright.
84: */
85: if (cansee(unc(obj->o_pos)) &&
86: mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
87: mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
88: draw(cw);
89: }
90: continue;
91: }
92:
93: /*
94: * Did we stop because of a monster or the hero? If we did
95: * not, we want to move our position back one because we could
96: * not actually make it this far.
97: */
98: if (!isalpha(ch) &&
99: !(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
100: obj->o_pos.y -= ydelta;
101: obj->o_pos.x -= xdelta;
102: }
103:
104: break;
105: }
106: }
107:
108:
109: /*
110: * fall:
111: * Drop an item someplace around here.
112: */
113:
114: void
115: fall(struct linked_list *item, bool pr)
116: {
117: register struct object *obj;
118: register struct room *rp;
119: register int i;
120: struct object *tobj;
121: struct linked_list *titem;
122: coord *fpos;
123:
124: obj = OBJPTR(item);
125: /*
126: * try to drop the item, look up to 3 squares away for now
127: */
128: for (i=1; i<4; i++) {
129: if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL)
130: break;
131: }
132:
133: if (fpos != NULL) {
134: if (obj->o_group) { /* try to add groups together */
135: for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
136: tobj = OBJPTR(titem);
137: if (tobj->o_group == obj->o_group &&
138: tobj->o_pos.y == fpos->y &&
139: tobj->o_pos.x == fpos->x) {
140: tobj->o_count += obj->o_count;
141: o_discard(item);
142: return;
143: }
144: }
145: }
146: mvaddch(fpos->y, fpos->x, obj->o_type);
147: obj->o_pos = *fpos;
148: if ((rp = roomin(&hero)) != NULL &&
149: lit_room(rp)) {
150: light(&hero);
151: mvwaddch(cw, hero.y, hero.x, PLAYER);
152: }
153: attach(lvl_obj, item);
154: return;
155: }
156: if (pr) {
157: msg("The %s vanishes as it hits the ground.",
158: weaps[obj->o_which].w_name);
159: }
160: o_discard(item);
161: }
162:
163:
164: /*
165: * Does the missile hit the monster
166: */
167:
168: bool
169: hit_monster(int y, int x, struct object *obj, struct thing *tp)
170: {
171: static coord mp;
172:
173: mp.y = y;
174: mp.x = x;
175: if (tp == &player) {
176: /* Make sure there is a monster where it landed */
177: if (!isalpha(mvwinch(mw, y, x))) {
178: return(FALSE);
179: }
180:
181: /* Player hits monster */
182: return(fight(&mp, obj, TRUE));
183: } else {
184: if (!ce(mp, hero)) {
185: /* Monster hits monster */
186: return(skirmish(tp, &mp, obj, TRUE));
187: }
188:
189: /* Monster hits player */
190: return(attack(tp, obj, TRUE));
191: }
192: }
193:
194: /*
195: * init_weapon:
196: * Set up the initial goodies for a weapon
197: */
198:
199: void
200: init_weapon(struct object *weap, char type)
201: {
202: register struct init_weps *iwp;
203:
204: iwp = &weaps[type];
205: strncpy(weap->o_damage, iwp->w_dam, sizeof(weap->o_damage));
206: strncpy(weap->o_hurldmg, iwp->w_hrl, sizeof(weap->o_hurldmg));
207: weap->o_launch = iwp->w_launch;
208: weap->o_flags = iwp->w_flags;
209: weap->o_weight = iwp->w_wght;
210: if (weap->o_flags & ISMANY) {
211: weap->o_count = rnd(8) + 8;
212: weap->o_group = newgrp();
213: } else {
214: weap->o_count = 1;
215: }
216: }
217:
218: /*
219: * missile:
220: * Fire a missile in a given direction
221: */
222:
223: void
224: missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
225: {
226: register struct object *obj;
227: register struct linked_list *nitem;
228: char ch;
229:
230: /*
231: * Get which thing we are hurling
232: */
233: if (item == NULL) {
234: return;
235: }
236: obj = OBJPTR(item);
237: if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
238: boomerang(ydelta, xdelta, item, tp);
239: return;
240: }
241:
242: if (!dropcheck(obj)) return; /* Can we get rid of it? */
243:
244: if(!(obj->o_flags & ISMISL)) {
245: while (TRUE) {
246: msg(terse ? "Really throw? (y or n): "
247: : "Do you really want to throw %s? (y or n): ",
248: inv_name(obj, TRUE));
249: mpos = 0;
250: ch = readchar();
251: if (ch == 'n' || ch == ESCAPE) {
252: after = FALSE;
253: return;
254: }
255: if (ch == 'y')
256: break;
257: }
258: }
259: /*
260: * Get rid of the thing. If it is a non-multiple item object, or
261: * if it is the last thing, just drop it. Otherwise, create a new
262: * item with a count of one.
263: */
264: if (obj->o_count < 2) {
265: detach(tp->t_pack, item);
266: if (tp->t_pack == pack) {
267: inpack--;
268: }
269: }
270: else {
271: obj->o_count--;
272: nitem = (struct linked_list *) new_item(sizeof *obj);
273: obj = OBJPTR(nitem);
274: *obj = *(OBJPTR(item));
275: obj->o_count = 1;
276: item = nitem;
277: }
278: updpack(FALSE, tp);
279: do_motion(obj, ydelta, xdelta, tp);
280: /*
281: * AHA! Here it has hit something. If it is a wall or a door,
282: * or if it misses (combat) the monster, put it on the floor
283: */
284: if (!hit_monster(unc(obj->o_pos), obj, tp)) {
285: fall(item, TRUE);
286: }
287: mvwaddch(cw, hero.y, hero.x, PLAYER);
288: }
289:
290: /*
291: * num:
292: * Figure out the plus number for armor/weapons
293: */
294:
295: char *
296: num(int n1, int n2)
297: {
298: static char numbuf[LINELEN];
299:
300: if (n1 == 0 && n2 == 0) {
301: return "+0";
302: }
303: if (n2 == 0) {
304: sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
305: } else {
306: sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
307: }
308: return(numbuf);
309: }
310:
311: /*
312: * wield:
313: * Pull out a certain weapon
314: */
315:
316: void
317: wield(void)
318: {
319: register struct linked_list *item;
320: register struct object *obj, *oweapon;
321:
322: /*
323: * It takes 2 movement periods to unwield a weapon and 2 movement
324: * periods to wield a weapon.
325: */
326: if (player.t_action != C_WIELD) {
327: player.t_action = C_WIELD;
328: player.t_using = NULL; /* Make sure this is NULL! */
329: if (cur_weapon != NULL) {
330: player.t_no_move = 2 * movement(&player);
331: return;
332: }
333: }
334:
335: if ((oweapon = cur_weapon) != NULL) {
336: /* At this point we have waited at least 2 units */
337: if (!dropcheck(cur_weapon)) {
338: cur_weapon = oweapon;
339: player.t_action = A_NIL;
340: return;
341: }
342: if (terse)
343: addmsg("Was ");
344: else
345: addmsg("You were ");
346: msg("wielding %s", inv_name(oweapon, TRUE));
347: }
348:
349: /* We we have something picked out? */
350: if (player.t_using == NULL) {
351: /* Now, what does he want to wield? */
352: if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
353: player.t_action = A_NIL;
354: after = FALSE;
355: return;
356: }
357: player.t_using = item;
358: player.t_no_move = 2 * movement(&player);
359: return;
360: }
361:
362: /* We have waited our time, let's wield the weapon */
363: item = player.t_using;
364: player.t_using = NULL;
365: player.t_action = A_NIL;
366:
367: obj = OBJPTR(item);
368:
369: if (is_current(obj)) {
370: msg("Item in use.");
371: after = FALSE;
372: return;
373: }
374: if (player.t_ctype != C_FIGHTER &&
375: player.t_ctype != C_RANGER &&
376: player.t_ctype != C_PALADIN &&
377: obj->o_type == WEAPON &&
378: (obj->o_which == TWOSWORD ||
379: (obj->o_which == BASWORD &&
380: player.t_ctype != C_ASSASIN))) {
381: msg("Only fighter types can wield a %s",
382: weaps[obj->o_which].w_name);
383: return;
384: }
385: if (terse) {
386: addmsg("W");
387: } else {
388: addmsg("You are now w");
389: }
390: msg("ielding %s", inv_name(obj, TRUE));
391: cur_weapon = obj;
392: }
393:
CVSweb