comparison rogue5/pack.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 e5a15b09ce1d
comparison
equal deleted inserted replaced
32:2dcd75e6a736 33:f502bf60e6e4
1 /*
2 * Routines to deal with the pack
3 *
4 * @(#)pack.c 4.40 (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 <string.h>
14 #include <curses.h>
15 #include <ctype.h>
16 #include "rogue.h"
17
18 /*
19 * update_mdest:
20 * Called after picking up an object, before discarding it.
21 * If this was the object of something's desire, that monster will
22 * get mad and run at the hero
23 */
24 update_mdest(obj)
25 register THING *obj;
26 {
27 register THING *mp;
28
29 for (mp = mlist; mp != NULL; mp = next(mp))
30 if (mp->t_dest == &obj->o_pos)
31 mp->t_dest = &hero;
32 }
33
34 /*
35 * add_pack:
36 * Pick up an object and add it to the pack. If the argument is
37 * non-null use it as the linked_list pointer instead of gettting
38 * it off the ground.
39 */
40
41 void
42 add_pack(THING *obj, int silent)
43 {
44 THING *op, *lp;
45 int from_floor;
46 int discarded = 0;
47
48 from_floor = FALSE;
49 if (obj == NULL)
50 {
51 if ((obj = find_obj(hero.y, hero.x)) == NULL)
52 return;
53 from_floor = TRUE;
54 }
55
56 /*
57 * Check for and deal with scare monster scrolls
58 */
59 if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
60 if (obj->o_flags & ISFOUND)
61 {
62 detach(lvl_obj, obj);
63 mvaddch(hero.y, hero.x, floor_ch());
64 chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
65 update_mdest(obj);
66 discarded = 1;
67 discard(obj);
68 msg("the scroll turns to dust as you pick it up");
69 return;
70 }
71
72 if (pack == NULL)
73 {
74 pack = obj;
75 obj->o_packch = pack_char();
76 inpack++;
77 }
78 else
79 {
80 lp = NULL;
81 for (op = pack; op != NULL; op = next(op))
82 {
83 if (op->o_type != obj->o_type)
84 lp = op;
85 else
86 {
87 while (op->o_type == obj->o_type && op->o_which != obj->o_which)
88 {
89 lp = op;
90 if (next(op) == NULL)
91 break;
92 else
93 op = next(op);
94 }
95 if (op->o_type == obj->o_type && op->o_which == obj->o_which)
96 {
97 if (ISMULT(op->o_type))
98 {
99 if (!pack_room(from_floor, obj))
100 return;
101 op->o_count++;
102 dump_it:
103 update_mdest(obj);
104 discard(obj);
105 obj = op;
106 discarded = 1;
107 lp = NULL;
108 goto out;
109 }
110 else if (obj->o_group)
111 {
112 lp = op;
113 while (op->o_type == obj->o_type
114 && op->o_which == obj->o_which
115 && op->o_group != obj->o_group)
116 {
117 lp = op;
118 if (next(op) == NULL)
119 break;
120 else
121 op = next(op);
122 }
123 if (op->o_type == obj->o_type
124 && op->o_which == obj->o_which
125 && op->o_group == obj->o_group)
126 {
127 op->o_count += obj->o_count;
128 inpack--;
129 if (!pack_room(from_floor, obj))
130 return;
131 goto dump_it;
132 }
133 }
134 else
135 lp = op;
136 }
137 out:
138 break;
139 }
140 }
141
142 if (lp != NULL)
143 {
144 if (!pack_room(from_floor, obj))
145 return;
146 else
147 {
148 obj->o_packch = pack_char();
149 next(obj) = next(lp);
150 prev(obj) = lp;
151 if (next(lp) != NULL)
152 prev(next(lp)) = obj;
153 next(lp) = obj;
154 }
155 }
156 }
157
158 obj->o_flags |= ISFOUND;
159
160 /*
161 * If this was the object of something's desire, that monster will
162 * get mad and run at the hero.
163 */
164 if (!discarded)
165 update_mdest(obj);
166
167 if (obj->o_type == AMULET)
168 amulet = TRUE;
169 /*
170 * Notify the user
171 */
172 if (!silent)
173 {
174 if (!terse)
175 addmsg("you now have ");
176 msg("%s (%c)", inv_name(obj, !terse), obj->o_packch);
177 }
178 }
179
180 /*
181 * pack_room:
182 * See if there's room in the pack. If not, print out an
183 * appropriate message
184 */
185 int
186 pack_room(int from_floor, THING *obj)
187 {
188 if (++inpack > MAXPACK)
189 {
190 if (!terse)
191 addmsg("there's ");
192 addmsg("no room");
193 if (!terse)
194 addmsg(" in your pack");
195 endmsg();
196 if (from_floor)
197 move_msg(obj);
198 inpack = MAXPACK;
199 return FALSE;
200 }
201
202 if (from_floor)
203 {
204 detach(lvl_obj, obj);
205 mvaddch(hero.y, hero.x, floor_ch());
206 chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
207 }
208
209 return TRUE;
210 }
211
212 /*
213 * leave_pack:
214 * take an item out of the pack
215 */
216 THING *
217 leave_pack(THING *obj, int newobj, int all)
218 {
219 THING *nobj;
220
221 inpack--;
222 nobj = obj;
223 if (obj->o_count > 1 && !all)
224 {
225 last_pick = obj;
226 obj->o_count--;
227 if (obj->o_group)
228 inpack++;
229 if (newobj)
230 {
231 nobj = new_item();
232 *nobj = *obj;
233 next(nobj) = NULL;
234 prev(nobj) = NULL;
235 nobj->o_count = 1;
236 }
237 }
238 else
239 {
240 last_pick = NULL;
241 pack_used[obj->o_packch - 'a'] = FALSE;
242 detach(pack, obj);
243 }
244 return nobj;
245 }
246
247 /*
248 * pack_char:
249 * Return the next unused pack character.
250 */
251 int
252 pack_char(void)
253 {
254 int *bp;
255
256 for (bp = pack_used; *bp; bp++)
257 continue;
258 *bp = TRUE;
259 return ((int)(bp - pack_used) + 'a');
260 }
261
262 /*
263 * inventory:
264 * List what is in the pack. Return TRUE if there is something of
265 * the given type.
266 */
267 int
268 inventory(const THING *list, int type)
269 {
270 static char inv_temp[MAXSTR];
271
272 n_objs = 0;
273 for (; list != NULL; list = next(list))
274 {
275 if (type && type != list->o_type && !(type == CALLABLE &&
276 list->o_type != FOOD && list->o_type != AMULET) &&
277 !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
278 continue;
279 n_objs++;
280 #ifdef MASTER
281 if (!list->o_packch)
282 strcpy(inv_temp, "%s");
283 else
284 #endif
285 sprintf(inv_temp, "%c) %%s", list->o_packch);
286 msg_esc = TRUE;
287 if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
288 {
289 msg_esc = FALSE;
290 msg("");
291 return TRUE;
292 }
293 msg_esc = FALSE;
294 }
295 if (n_objs == 0)
296 {
297 if (terse)
298 msg(type == 0 ? "empty handed" :
299 "nothing appropriate");
300 else
301 msg(type == 0 ? "you are empty handed" :
302 "you don't have anything appropriate");
303 return FALSE;
304 }
305 end_line();
306 return TRUE;
307 }
308
309 /*
310 * pick_up:
311 * Add something to characters pack.
312 */
313
314 void
315 pick_up(int ch)
316 {
317 THING *obj;
318
319 if (on(player, ISLEVIT))
320 return;
321
322 obj = find_obj(hero.y, hero.x);
323 if (move_on)
324 move_msg(obj);
325 else
326 switch (ch)
327 {
328 case GOLD:
329 if (obj == NULL)
330 return;
331 money(obj->o_goldval);
332 detach(lvl_obj, obj);
333 update_mdest(obj);
334 discard(obj);
335 proom->r_goldval = 0;
336 break;
337 default:
338 #ifdef MASTER
339 debug("Where did you pick a '%s' up???", unctrl(ch));
340 #endif
341 case ARMOR:
342 case POTION:
343 case FOOD:
344 case WEAPON:
345 case SCROLL:
346 case AMULET:
347 case RING:
348 case STICK:
349 add_pack(NULL, FALSE);
350 break;
351 }
352 }
353
354 /*
355 * move_msg:
356 * Print out the message if you are just moving onto an object
357 */
358
359 void
360 move_msg(const THING *obj)
361 {
362 if (!terse)
363 addmsg("you ");
364 msg("moved onto %s", inv_name(obj, TRUE));
365 }
366
367 /*
368 * picky_inven:
369 * Allow player to inventory a single item
370 */
371
372 void
373 picky_inven(void)
374 {
375 THING *obj;
376 int mch;
377
378 if (pack == NULL)
379 msg("you aren't carrying anything");
380 else if (next(pack) == NULL)
381 msg("a) %s", inv_name(pack, FALSE));
382 else
383 {
384 msg(terse ? "item: " : "which item do you wish to inventory: ");
385 mpos = 0;
386 if ((mch = readchar()) == ESCAPE)
387 {
388 msg("");
389 return;
390 }
391 for (obj = pack; obj != NULL; obj = next(obj))
392 if (mch == obj->o_packch)
393 {
394 msg("%c) %s", mch, inv_name(obj, FALSE));
395 return;
396 }
397 msg("'%s' not in pack", unctrl(mch));
398 }
399 }
400
401 /*
402 * get_item:
403 * Pick something out of a pack for a purpose
404 */
405 THING *
406 get_item(const char *purpose, int type)
407 {
408 THING *obj;
409 int ch;
410
411 if (pack == NULL)
412 msg("you aren't carrying anything");
413 else if (again)
414 if (last_pick)
415 return last_pick;
416 else
417 msg("you ran out");
418 else
419 {
420 for (;;)
421 {
422 if (!terse)
423 addmsg("which object do you want to ");
424 addmsg(purpose);
425 if (terse)
426 addmsg(" what");
427 msg("? (* for list): ");
428 ch = readchar();
429 mpos = 0;
430 /*
431 * Give the poor player a chance to abort the command
432 */
433 if (ch == ESCAPE)
434 {
435 reset_last();
436 after = FALSE;
437 msg("");
438 return NULL;
439 }
440 n_objs = 1; /* normal case: person types one char */
441 if (ch == '*')
442 {
443 mpos = 0;
444 if (inventory(pack, type) == 0)
445 {
446 after = FALSE;
447 return NULL;
448 }
449 continue;
450 }
451 for (obj = pack; obj != NULL; obj = next(obj))
452 if (obj->o_packch == ch)
453 break;
454 if (obj == NULL)
455 {
456 msg("'%s' is not a valid item",unctrl(ch));
457 continue;
458 }
459 else {
460 msg("");
461 return obj;
462 }
463 }
464 }
465 return NULL;
466 }
467
468 /*
469 * money:
470 * Add or subtract gold from the pack
471 */
472
473 void
474 money(int value)
475 {
476 purse += value;
477 mvaddch(hero.y, hero.x, floor_ch());
478 chat(hero.y, hero.x) = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
479 if (value > 0)
480 {
481 if (!terse)
482 addmsg("you found ");
483 msg("%d gold pieces", value);
484 }
485 }
486
487 /*
488 * floor_ch:
489 * Return the appropriate floor character for her room
490 */
491 int
492 floor_ch(void)
493 {
494 if (proom->r_flags & ISGONE)
495 return PASSAGE;
496 return (show_floor() ? FLOOR : ' ');
497 }
498
499 /*
500 * floor_at:
501 * Return the character at hero's position, taking see_floor
502 * into account
503 */
504 int
505 floor_at(void)
506 {
507 int ch;
508
509 ch = chat(hero.y, hero.x);
510 if (ch == FLOOR)
511 ch = floor_ch();
512 return ch;
513 }
514
515 /*
516 * reset_last:
517 * Reset the last command when the current one is aborted
518 */
519
520 void
521 reset_last(void)
522 {
523 last_comm = l_last_comm;
524 last_dir = l_last_dir;
525 last_pick = l_last_pick;
526 }