comparison rogue3/pack.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children d9e44e18eeec
comparison
equal deleted inserted replaced
-1:000000000000 0:527e2150eaf0
1 /*
2 * Routines to deal with the pack
3 *
4 * @(#)pack.c 3.6 (Berkeley) 6/15/81
5 *
6 * Rogue: Exploring the Dungeons of Doom
7 * Copyright (C) 1980, 1981 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 <ctype.h>
15 #include "rogue.h"
16
17 /*
18 * add_pack:
19 * Pick up an object and add it to the pack. If the argument is non-null
20 * use it as the linked_list pointer instead of gettting it off the ground.
21 */
22 void
23 add_pack(struct linked_list *item, int silent)
24 {
25 struct linked_list *ip, *lp;
26 struct object *obj, *op;
27 int exact, from_floor;
28
29 if (item == NULL)
30 {
31 from_floor = TRUE;
32 if ((item = find_obj(hero.y, hero.x)) == NULL)
33 return;
34 }
35 else
36 from_floor = FALSE;
37 obj = (struct object *) ldata(item);
38 /*
39 * Link it into the pack. Search the pack for a object of similar type
40 * if there isn't one, stuff it at the beginning, if there is, look for one
41 * that is exactly the same and just increment the count if there is.
42 * it that. Food is always put at the beginning for ease of access, but
43 * is not ordered so that you can't tell good food from bad. First check
44 * to see if there is something in thr same group and if there is then
45 * increment the count.
46 */
47 if (obj->o_group)
48 {
49 for (ip = pack; ip != NULL; ip = next(ip))
50 {
51 op = (struct object *) ldata(ip);
52 if (op->o_group == obj->o_group)
53 {
54 /*
55 * Put it in the pack and notify the user
56 */
57 op->o_count++;
58 if (from_floor)
59 {
60 detach(lvl_obj, item);
61 mvaddch(hero.y, hero.x,
62 (roomin(&hero) == NULL ? PASSAGE : FLOOR));
63 }
64 discard(item);
65 item = ip;
66 goto picked_up;
67 }
68 }
69 }
70 /*
71 * Check if there is room
72 */
73 if (inpack == MAXPACK-1)
74 {
75 msg("You can't carry anything else.");
76 return;
77 }
78 /*
79 * Check for and deal with scare monster scrolls
80 */
81 if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
82 if (obj->o_flags & ISFOUND)
83 {
84 msg("The scroll turns to dust as you pick it up.");
85 detach(lvl_obj, item);
86 mvaddch(hero.y, hero.x, FLOOR);
87 return;
88 }
89 else
90 obj->o_flags |= ISFOUND;
91
92 inpack++;
93 if (from_floor)
94 {
95 detach(lvl_obj, item);
96 mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));
97 }
98 /*
99 * Search for an object of the same type
100 */
101 exact = FALSE;
102 for (ip = pack; ip != NULL; ip = next(ip))
103 {
104 op = (struct object *) ldata(ip);
105 if (obj->o_type == op->o_type)
106 break;
107 }
108 if (ip == NULL)
109 {
110 /*
111 * Put it at the end of the pack since it is a new type
112 */
113 for (ip = pack; ip != NULL; ip = next(ip))
114 {
115 op = (struct object *) ldata(ip);
116 if (op->o_type != FOOD)
117 break;
118 lp = ip;
119 }
120 }
121 else
122 {
123 /*
124 * Search for an object which is exactly the same
125 */
126 while (ip != NULL && op->o_type == obj->o_type)
127 {
128 if (op->o_which == obj->o_which)
129 {
130 exact = TRUE;
131 break;
132 }
133 lp = ip;
134 if ((ip = next(ip)) == NULL)
135 break;
136 op = (struct object *) ldata(ip);
137 }
138 }
139 if (ip == NULL)
140 {
141 /*
142 * Didn't find an exact match, just stick it here
143 */
144 if (pack == NULL)
145 pack = item;
146 else
147 {
148 lp->l_next = item;
149 item->l_prev = lp;
150 item->l_next = NULL;
151 }
152 }
153 else
154 {
155 /*
156 * If we found an exact match. If it is a potion, food, or a
157 * scroll, increase the count, otherwise put it with its clones.
158 */
159 if (exact && ISMULT(obj->o_type))
160 {
161 op->o_count++;
162 discard(item);
163 item = ip;
164 goto picked_up;
165 }
166 if ((item->l_prev = prev(ip)) != NULL)
167 item->l_prev->l_next = item;
168 else
169 pack = item;
170 item->l_next = ip;
171 ip->l_prev = item;
172 }
173 picked_up:
174 /*
175 * Notify the user
176 */
177 obj = (struct object *) ldata(item);
178 if (notify && !silent)
179 {
180 if (!terse)
181 addmsg("You now have ");
182 msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
183 }
184 if (obj->o_type == AMULET)
185 amulet = TRUE;
186 }
187
188 /*
189 * inventory:
190 * list what is in the pack
191 */
192 int
193 inventory(struct linked_list *list, int type)
194 {
195 struct object *obj;
196 int ch;
197 int n_objs;
198 char inv_temp[80];
199
200 n_objs = 0;
201 for (ch = 'a'; list != NULL; ch++, list = next(list))
202 {
203 obj = (struct object *) ldata(list);
204 if (type && type != obj->o_type && !(type == CALLABLE &&
205 (obj->o_type == SCROLL || obj->o_type == POTION ||
206 obj->o_type == RING || obj->o_type == STICK)))
207 continue;
208 switch (n_objs++)
209 {
210 /*
211 * For the first thing in the inventory, just save the string
212 * in case there is only one.
213 */
214 case 0:
215 sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
216 break;
217 /*
218 * If there is more than one, clear the screen, print the
219 * saved message and fall through to ...
220 */
221 case 1:
222 if (slow_invent)
223 msg(inv_temp);
224 else
225 {
226 wclear(hw);
227 waddstr(hw, inv_temp);
228 waddch(hw, '\n');
229 }
230 /*
231 * Print the line for this object
232 */
233 default:
234 if (slow_invent)
235 msg("%c) %s", ch, inv_name(obj, FALSE));
236 else
237 wprintw(hw, "%c) %s\n", ch, inv_name(obj, FALSE));
238 }
239 }
240 if (n_objs == 0)
241 {
242 if (terse)
243 msg(type == 0 ? "Empty handed." :
244 "Nothing appropriate");
245 else
246 msg(type == 0 ? "You are empty handed." :
247 "You don't have anything appropriate");
248 return FALSE;
249 }
250 if (n_objs == 1)
251 {
252 msg(inv_temp);
253 return TRUE;
254 }
255 if (!slow_invent)
256 {
257 mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
258 draw(hw);
259 wait_for(hw,' ');
260 clearok(cw, TRUE);
261 touchwin(cw);
262 }
263 return TRUE;
264 }
265
266 /*
267 * pick_up:
268 * Add something to characters pack.
269 */
270 void
271 pick_up(int ch)
272 {
273 switch(ch)
274 {
275 case GOLD:
276 money();
277 break;
278 default:
279 debug("Where did you pick that up???");
280 case ARMOR:
281 case POTION:
282 case FOOD:
283 case WEAPON:
284 case SCROLL:
285 case AMULET:
286 case RING:
287 case STICK:
288 add_pack(NULL, FALSE);
289 break;
290 }
291 }
292
293 /*
294 * picky_inven:
295 * Allow player to inventory a single item
296 */
297 void
298 picky_inven()
299 {
300 struct linked_list *item;
301 int ch, mch;
302
303 if (pack == NULL)
304 msg("You aren't carrying anything");
305 else if (next(pack) == NULL)
306 msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));
307 else
308 {
309 msg(terse ? "Item: " : "Which item do you wish to inventory: ");
310 mpos = 0;
311 if ((mch = readchar(cw)) == ESCAPE)
312 {
313 msg("");
314 return;
315 }
316 for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
317 if (ch == mch)
318 {
319 msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));
320 return;
321 }
322 if (!terse)
323 msg("'%s' not in pack", unctrl(mch));
324 msg("Range is 'a' to '%c'", --ch);
325 }
326 }
327
328 /*
329 * get_item:
330 * pick something out of a pack for a purpose
331 */
332 struct linked_list *
333 get_item(char *purpose, int type)
334 {
335 struct linked_list *obj;
336 int ch, och;
337
338 if (pack == NULL)
339 msg("You aren't carrying anything.");
340 else
341 {
342 for (;;)
343 {
344 if (!terse)
345 addmsg("Which object do you want to ");
346 addmsg(purpose);
347 if (terse)
348 addmsg(" what");
349 msg("? (* for list): ");
350 ch = readchar(cw);
351 mpos = 0;
352 /*
353 * Give the poor player a chance to abort the command
354 */
355 if (ch == ESCAPE || ch == CTRL('G'))
356 {
357 after = FALSE;
358 msg("");
359 return NULL;
360 }
361 if (ch == '*')
362 {
363 mpos = 0;
364 if (inventory(pack, type) == 0)
365 {
366 after = FALSE;
367 return NULL;
368 }
369 continue;
370 }
371 for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
372 if (ch == och)
373 break;
374 if (obj == NULL)
375 {
376 msg("Please specify a letter between 'a' and '%c'", och-1);
377 continue;
378 }
379 else
380 return obj;
381 }
382 }
383 return NULL;
384 }
385
386 int
387 pack_char(struct object *obj)