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