Annotation of early-roguelike/urogue/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: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
6: All rights reserved.
7:
8: Based on "Advanced Rogue"
9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
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 <ctype.h>
20: #include <string.h>
21: #include "rogue.h"
22:
23: /*
24: missile()
25: Fire a missile in a given direction
26: */
27:
28: void
29: missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp)
30: {
31: struct object *obj;
32: struct linked_list *nitem;
33:
34: if (item == NULL) /* Get which thing we are hurling */
35: return;
36:
37: obj = OBJPTR(item);
38:
39: if (!dropcheck(obj) || is_current(obj))
40: return;
41:
42: /*
43: * Get rid of the thing. If it is a non-multiple item object, or if
44: * it is the last thing, just drop it. Otherwise, create a new item
45: * with a count of one.
46: */
47:
48: if (obj->o_count < 2)
49: {
50: if (tp->t_pack == pack)
51: rem_pack(obj);
52: else
53: detach(tp->t_pack, item);
54: }
55: else
56: {
57: obj->o_count--;
58: nitem = (struct linked_list *) new_item(sizeof *obj);
59: obj = OBJPTR(nitem);
60: *obj = *(OBJPTR(item));
61: obj->o_count = 1;
62: item = nitem;
63: }
64:
65: switch (obj->o_type)
66: {
67: case ARTIFACT:
68: has_artifact &= ~(1 << obj->o_which);
69: break;
70:
71: case SCROLL:
72: if (obj->o_which == S_SCARE && obj->o_flags & ISBLESSED)
73: obj->o_flags &= ~ISBLESSED;
74: else
75: obj->o_flags |= ISCURSED;
76: }
77:
78: updpack();
79: obj->o_pos = do_motion(obj->o_type, ydelta, xdelta, tp);
80:
81: /*
82: * AHA! Here it has hit something. If it is a wall or a door, or if
83: * it misses (combat) the monster, put it on the floor
84: */
85:
86: if (!hit_monster(obj->o_pos.y, obj->o_pos.x, obj, tp))
87: {
88: if (obj->o_type == WEAPON && obj->o_which == GRENADE)
89: {
90: hearmsg("BOOOM!");
91: aggravate();
92:
93: if (ntraps + 1 < 2 * MAXTRAPS &&
94: fallpos(obj->o_pos, &traps[ntraps].tr_pos))
95: {
96: mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x,
97: TRAPDOOR);
98: traps[ntraps].tr_type = TRAPDOOR;
99: traps[ntraps].tr_flags = ISFOUND;
100: traps[ntraps].tr_show = TRAPDOOR;
101: ntraps++;
102: light(&hero);
103: }
104: discard(item);
105: }
106: else if (obj->o_flags & ISLOST)
107: {
108: if (obj->o_type == WEAPON)
109: addmsg("The %s", weaps[obj->o_which].w_name);
110: else
111: addmsg(inv_name(obj, LOWERCASE));
112:
113: msg(" vanishes in a puff of greasy smoke.");
114: discard(item);
115: }
116: else
117: {
118: fall(&player, item, TRUE, TRUE);
119:
120: if (obj->o_flags & CANRETURN)
121: msg("You have %s.", inv_name(obj, LOWERCASE));
122: }
123: }
124: else if (obj->o_flags & ISOWNED)
125: {
126: add_pack(item, NOMESSAGE);
127: msg("You have %s.", inv_name(obj, LOWERCASE));
128: }
129:
130: mvwaddch(cw, hero.y, hero.x, PLAYER);
131: }
132:
133: /*
134: do_motion()
135: do the actual motion on the screen done by an object
136: traveling across the room
137: */
138:
139: coord
140: do_motion(int ob, int ydelta, int xdelta, struct thing *tp)
141: {
142: coord pos;
143: /* Come fly with us ... */
144:
145: pos = tp->t_pos;
146:
147: for (;;)
148: {
149: int ch;
150:
151: /* Erase the old one */
152:
153: if (!ce(pos, tp->t_pos) &&
154: cansee(pos.y, pos.x) &&
155: mvwinch(cw, pos.y, pos.x) != ' ')
156: {
157: mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x));
158: }
159:
160: /* Get the new position */
161:
162: pos.y += ydelta;
163: pos.x += xdelta;
164:
165: if (shoot_ok(ch = winat(pos.y, pos.x)) &&
166: ch != DOOR && !ce(pos, hero))
167: {
168: /* It hasn't hit anything yet, so display it if it alright. */
169:
170: if (cansee(pos.y, pos.x) &&
171: mvwinch(cw, pos.y, pos.x) != ' ')
172: {
173: mvwaddch(cw, pos.y, pos.x, ob);
174: wrefresh(cw);
175: }
176:
177: continue;
178:
179: }
180: break;
181: }
182:
183: return(pos);
184: }
185:
186: /*
187: fall()
188: Drop an item someplace around here.
189: */
190:
191: void
192: fall(struct thing *tp, struct linked_list *item, int pr, int player_owned)
193: {
194: struct object *obj;
195: struct room *rp;
196: coord fpos;
197:
198: obj = OBJPTR(item);
199: rp = roomin(tp->t_pos);
200:
201: if (player_owned && obj->o_flags & CANRETURN)
202: {
203: add_pack(item, NOMESSAGE);
204: msg("You have %s.", inv_name(obj, LOWERCASE));
205: return;
206: }
207: else if (fallpos(obj->o_pos, &fpos))
208: {
209: if (obj->o_flags & CANBURN && obj->o_type == WEAPON
210: && obj->o_which == MOLOTOV
211: && ntraps + 1 < 2 * MAXTRAPS)
212: {
213: mvaddch(fpos.y, fpos.x, FIRETRAP);
214: traps[ntraps].tr_type = FIRETRAP;
215: traps[ntraps].tr_flags = ISFOUND;
216: traps[ntraps].tr_show = FIRETRAP;
217: traps[ntraps].tr_pos = fpos;
218: ntraps++;
219:
220: if (rp != NULL)
221: rp->r_flags &= ~ISDARK;
222: }
223: else
224: {
225: obj->o_pos = fpos;
226: add_obj(item, fpos.y, fpos.x);
227: }
228:
229: if (rp != NULL &&
230: (!(rp->r_flags & ISDARK) ||
231: (rp->r_flags & HASFIRE)))
232: {
233: light(&hero);
234: mvwaddch(cw, hero.y, hero.x, PLAYER);
235: }
236: return;
237: }
238:
239: /* get here only if there isn't a place to put it */
240:
241: if (pr)
242: {
243: if (cansee(obj->o_pos.y, obj->o_pos.x))
244: {
245: if (obj->o_type == WEAPON)
246: addmsg("The %s", weaps[obj->o_which].w_name);
247: else
248: addmsg(inv_name(obj, LOWERCASE));
249:
250: msg(" vanishes as it hits the ground.");
251: }
252: }
253: discard(item);
254: }
255:
256: /*
257: init_weapon()
258: Set up the initial goodies for a weapon
259: */
260:
261: void
262: init_weapon(struct object *weap, int type)
263: {
264: struct init_weps *iwp = &weaps[type];
265:
266: weap->o_damage = iwp->w_dam;
267: weap->o_hurldmg = iwp->w_hrl;
268: weap->o_launch = iwp->w_launch;
269: weap->o_flags = iwp->w_flags;
270: weap->o_weight = iwp->w_wght;
271:
272: if (weap->o_flags & ISMANY)
273: {
274: weap->o_count = rnd(8) + 8;
275: weap->o_group = ++group;
276: }
277: else
278: weap->o_count = 1;
279: }
280:
281: /*
282: hit_monster()
283: does the missile hit the target?
284: */
285:
286: int
287: hit_monster(int y, int x, struct object *weapon, struct thing *thrower)
288: {
289: struct linked_list *mon;
290: coord target;
291:
292: target.y = y;
293: target.x = x;
294:
295: if (thrower == &player)
296: return(fight(&target, weapon, THROWN));
297:
298: if (ce(target, hero))
299: {
300: if (good_monster(*thrower))
301: {
302: if (on(*thrower, ISFAMILIAR))
303: msg("Please get out of the way, Master! I nearly hit you.");
304: else
305: msg("Get out of the way %s!", whoami);
306:
307: return(FALSE);
308: }
309:
310: return(attack(thrower, weapon, THROWN));
311: }
312:
313: if ((mon = find_mons(y, x)) != NULL)
314: return(mon_mon_attack(thrower, mon, weapon, THROWN));
315: else
316: return(FALSE);
317: }
318:
319:
320: /*
321: num()
322: Figure out the plus number for armor/weapons
323: */
324:
325: char *
326: num(int n1, int n2, char *buf)
327: {
328: if (buf == NULL)
329: return("UltraRogue Error #104");
330:
331: if (n1 == 0 && n2 == 0)
332: {
333: strcpy(buf,"+0");
334: return(buf);
335: }
336:
337: if (n2 == 0)
338: sprintf(buf, "%s%d", n1 < 0 ? "" : "+", n1);
339: else
340: sprintf(buf, "%s%d, %s%d", n1 < 0 ? "" : "+",
341: n1, n2 < 0 ? "" : "+", n2);
342:
343: return(buf);
344: }
345:
346: /*
347: wield()
348: Pull out a certain weapon
349: */
350:
351: void
352: wield(void)
353: {
354: struct linked_list *item;
355: struct object *obj, *oweapon;
356:
357: oweapon = cur_weapon;
358:
359: if (!dropcheck(cur_weapon))
360: {
361: cur_weapon = oweapon;
362: return;
363: }
364:
365: cur_weapon = oweapon;
366:
367: if ((item = get_item("wield", WEAPON)) == NULL)
368: {
369: after = FALSE;
370: return;
371: }
372:
373: obj = OBJPTR(item);
374:
375: if (is_current(obj))
376: {
377: after = FALSE;
378: return;
379: }
380:
381: wield_ok(&player, obj, TRUE);
382:
383: msg("You are now wielding %s.", inv_name(obj, LOWERCASE));
384:
385: cur_weapon = obj;
386: }
387:
388: /*
389: fallpos()
390: pick a random position around the given (y, x) coordinates
391: */
392:
393: int
394: fallpos(coord pos, coord *newpos) /*ARGSUSED*/
395: {
396: int y, x, cnt;
397: coord places[9];
398:
399: cnt = 0;
400:
401: /* look for all the places that qualify */
402:
403: for (y = pos.y - 1; y <= pos.y + 1; y++)
404: {
405: for (x = pos.x - 1; x <= pos.x + 1; x++)
406: {
407: switch(CCHAR(mvwinch(stdscr,y,x)))
408: {
409: case GOLD:
410: case POTION:
411: case SCROLL:
412: case FOOD:
413: case WEAPON:
414: case ARMOR:
415: case RING:
416: case STICK:
417: case FLOOR:
418: case PASSAGE:
419: case ARTIFACT:
420: places[cnt].y = y;
421: places[cnt].x = x;
422: cnt++;
423: }
424: }
425: }
426:
427: /* now, pick one of the places, if there are any */
428:
429: if (cnt > 0)
430: {
431: int which = rnd(cnt);
432:
433: newpos->y = places[which].y;
434: newpos->x = places[which].x;
435:
436: debug("Dropping object at %d, %d", newpos->y, newpos->x);
437: }
438:
439: return(cnt);
440: }
441:
442: /*
443: wield_ok()
444: enforce player class weapons restrictions
445: */
446:
447: int
448: wield_ok(struct thing *wieldee, struct object *obj, int print_message)
449: {
450: int ret_val = TRUE;
451: int class_type = wieldee->t_ctype;
452:
453: if (obj->o_type != WEAPON)
454: {
455: ret_val = FALSE;
456: return(ret_val);
457: }
458: else
459: switch (class_type)
460: {
461: case C_MAGICIAN: /* need one hand free */
462: case C_ILLUSION:
463: if (obj->o_flags & ISTWOH)
464: ret_val = FALSE;
465: break;
466:
467: case C_THIEF: /* need portable weapon */
468: case C_ASSASIN:
469: case C_NINJA:
470: if (obj->o_flags & ISTWOH)
471: ret_val = FALSE;
472: break;
473:
474: case C_CLERIC: /* No sharp weapons */
475: if (obj->o_flags & ISSHARP)
476: ret_val = FALSE;
477: break;
478:
479: case C_DRUID: /* No non-silver metal weapons */
480: if (obj->o_flags & ISMETAL && !(obj->o_flags & ISSILVER))
481: ret_val = FALSE;
482: break;
483:
484: case C_PALADIN: /* must wield sharp stuff */
485: if ((obj->o_flags & ISSHARP) == FALSE)
486: ret_val = FALSE;
487: break;
488:
489: case C_FIGHTER: /* wield anything */
490: case C_RANGER:
491: case C_MONSTER:
492: break;
493:
494: default: /* Unknown class */
495: debug("Unknown class %d.", class_type);
496: break;
497: }
498:
499: if (itemweight(obj) > 18 * pstats.s_str)
500: {
501: if (wieldee == &player && print_message == TRUE)
502: msg("That is too heavy for you to swing effectively!");
503:
504: ret_val = FALSE;
505: return(ret_val);
506: }
507:
508: if (ret_val == FALSE && print_message == MESSAGE)
509: switch (class_type)
510: {
511: case C_MAGICIAN:
512: case C_ILLUSION:
513: msg("You'll find it hard to cast spells while wielding that!");
514: break;
515:
516: case C_THIEF:
517: case C_ASSASIN:
518: case C_NINJA:
519: msg("Don't expect to backstab anyone while wielding that!");
520: break;
521:
522: case C_CLERIC:
523: case C_DRUID:
524: case C_PALADIN:
525: msg("Your god strongly disapproves of your wielding that!");
526: break;
527:
528: case C_FIGHTER:
529: case C_RANGER:
530: case C_MONSTER:
531: break;
532: }
533:
534: return(ret_val);
535: }
536:
537: /*
538: shoot_ok()
539: returns true if it is ok for type to shoot over ch
540: */
541:
542: int
543: shoot_ok(int ch)
544: {
545: switch(ch)
546: {
547: case ' ':
548: case '|':
549: case '-':
550: case SECRETDOOR:
551: return(FALSE);
552:
553: default:
554: return(!isalpha(ch));
555: }
556: }
CVSweb