comparison urogue/pack.c @ 256:c495a4f288c6

Import UltraRogue from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 31 Jan 2017 19:56:04 -0500
parents
children 74351bf23e5e
comparison
equal deleted inserted replaced
253:d9badb9c0179 256:c495a4f288c6
1 /*
2 pack.c - Routines to deal with the pack.
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 /*
20 Notes
21
22 The new pack is implemented through the use of bags,
23 and items are classed by their types (see rogue.h) which also
24 happen to be their display character.
25 */
26
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include "rogue.h"
30
31 #define ESCAPE_EXIT(x) if (x == ESCAPE) {after = FALSE; msg(""); return(NULL);}
32 #define BAD_NEWS -1
33 #define BAD_LIST ((struct linked_list *) BAD_NEWS)
34 #define GOOD_NEWS 0
35
36 static char type_list[] = "!?])/=:,"; /* things to inventory */
37
38 /*
39 swap_top()
40 Takes an stacked object and exchanges places with the top
41 object. <node> must belong to the <top>'s stacked object list.
42 */
43
44 void
45 swap_top(struct linked_list *top, struct linked_list *node)
46 {
47 struct object *obt, *obn;
48
49 obt = OBJPTR(top);
50 obn = OBJPTR(node);
51
52 detach((obt->next_obj), node); /* Take it out of the stack */
53 attach(lvl_obj, node); /* and put it into the level */
54 detach(lvl_obj, top); /* Remove item from level */
55
56 obn->next_obj = obt->next_obj;
57
58 if (obn->next_obj)
59 obn->next_obj->l_prev = NULL;
60
61 attach((obn->next_obj), top);
62 }
63
64
65 /*
66 get_all()
67 Get as many stacked items as possible.
68 */
69
70 void
71 get_all(struct linked_list *top)
72 {
73 struct linked_list *node;
74 struct object *obt;
75
76 while (top)
77 {
78 obt = OBJPTR(top);
79 node = obt->next_obj;
80
81 rem_obj(top, FALSE);
82
83 if (!add_pack(top, FALSE))
84 return;
85
86 top = node;
87 }
88 }
89
90
91 /*
92 get_stack()
93 Allows the user to chose from a stack of items.
94 */
95
96 struct linked_list *
97 get_stack(struct linked_list *item)
98 {
99 struct object *obj;
100 char buf[2 * LINELEN];
101 int i = 0, j;
102 struct linked_list *ll;
103 mpos = 0;
104 obj = OBJPTR(item);
105
106 ll = obj->next_obj;
107
108 sprintf(buf, "You are standing on top of the following items: ");
109 add_line(buf);
110 sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
111 add_line(buf);
112
113 while (ll)
114 {
115 i++;
116 obj = OBJPTR(ll);
117 sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE));
118 add_line(buf);
119 ll = next(ll);
120 }
121
122 end_line();
123
124 msg("Which one do you want to pick up? [* for all] ");
125
126 switch(get_string(buf, cw))
127 {
128 case NORM:
129 break;
130 case QUIT: /* pick up nothing */
131 msg("");
132 return (NULL);
133 }
134
135 if (buf[0] == '*')
136 {
137 get_all(item);
138 msg("");
139 return(NULL);
140 }
141 else
142 {
143 i = atoi(buf);
144
145 if (i)
146 {
147 obj = OBJPTR(item);
148 ll = obj->next_obj;
149 j = 1;
150
151 while (ll && (j != i))
152 {
153 ll = next(ll);
154 j++;
155 }
156
157 if (ll)
158 {
159 swap_top(item, ll);
160 return(ll);
161 }
162 else
163 {
164 debug("Got past last item while picking up.");
165 return(item);
166 }
167 }
168 else
169 return (item);
170 }
171 }
172
173 /*
174 add_pack()
175 Pick up an object and add it to the pack. If the argument is
176 non-null use it as the linked_list pointer instead of getting it off the
177 ground.
178 */
179
180 int
181 add_pack(struct linked_list *item, int print_message)
182 {
183 struct object *obj, *op;
184 int from_floor;
185
186 if (item == NULL)
187 {
188 from_floor = TRUE;
189
190 if ((item = find_obj(hero.y, hero.x)) == NULL)
191 {
192 msg("Nothing to pick up.");
193 return(FALSE);
194 }
195 }
196 else
197 from_floor = FALSE;
198
199 if (from_floor)
200 {
201 item = get_stack(item);
202
203 if (!item)
204 return(FALSE);
205 }
206
207 obj = OBJPTR(item);
208
209 /* If it is gold, just add its value to rogue's purse and get rid of */
210
211 if (obj->o_type == GOLD)
212 {
213 struct linked_list *mitem;
214 struct thing *tp;
215
216 if (print_message)
217 {
218 if (!terse)
219 addmsg("You found ");
220
221 msg("%d gold pieces.", obj->o_count);
222 }
223
224 /*
225 * First make sure no greedy monster is after this gold. If
226 * so, make the monster run after the rogue instead.
227 */
228
229 for (mitem = mlist; mitem != NULL; mitem = next(mitem))
230 {
231 tp = THINGPTR(mitem);
232
233 if (tp->t_horde==obj)
234 {
235 tp->t_ischasing = TRUE;
236 tp->t_chasee = &player;
237 tp->t_horde = NULL;
238 }
239 }
240
241 /*
242 * This will cause problems if people are able to drop and
243 * pick up gold, or when GOLDSTEAL monsters are killed.
244 */
245
246 /* Thieves get EXP for gold they pick up */
247
248 if (player.t_ctype == C_THIEF)
249 {
250 pstats.s_exp += obj->o_count / 4;
251 check_level();
252 }
253
254 purse += obj->o_count;
255
256 if (from_floor)
257 rem_obj(item, TRUE); /* Remove object from the level */
258
259 return (TRUE);
260 }
261
262 /* see if he can carry any more weight */
263
264 if (itemweight(obj) + pstats.s_pack > pstats.s_carry)
265 {
266 msg("Too much for you to carry.");
267
268 if (print_message)
269 {
270 msg("%s onto %s", terse ? "Moved" : "You moved",
271 inv_name(obj, LOWERCASE));
272 }
273
274 return(FALSE);
275 }
276
277 /*
278 * Link it into the pack. If the item can be grouped, try to find its
279 * neighbors and bump the count. A special case is food, which can't
280 * be grouped, but an exact match allows the count to get
281 * incremented.
282 */
283
284 if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL)
285 {
286 op->o_count += obj->o_count; /* add it to the rest */
287
288 if (from_floor)
289 rem_obj(item, FALSE);
290
291 pack_report(op, print_message, "You now have ");
292
293 return(TRUE);
294 }
295
296 /* Check for and deal with scare monster scrolls */
297
298 if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
299 if (obj->o_flags & ISCURSED)
300 {
301 msg("The scroll turns to dust as you pick it up.");
302 rem_obj(item, TRUE);
303 return(TRUE);
304 }
305
306 /* Check if there is room */
307
308 if (count_bag(pack, obj->o_type, NULL) == max_print())
309 {
310 msg("You have no room for more %s.", name_type(obj->o_type));
311
312 if (print_message)
313 {
314 obj = OBJPTR(item);
315 msg("%s onto %s.", terse ? "Moved" : "You moved",
316 inv_name(obj, LOWERCASE));
317 }
318
319 return(FALSE);
320 }
321
322 /*
323 * finally, add the new item to the bag, and free up the linked list
324 * on top of it.
325 */
326
327 if (from_floor)
328 rem_obj(item, FALSE);
329
330 push_bag(&pack, obj);
331 pack_report(obj, print_message, "You now have ");
332 ur_free(item);
333
334 return(TRUE); /* signal success */
335 }
336
337 /*
338 pack_report()
339 Notify the user about the results of the pack operation and do some
340 post processing.
341 */
342
343 void
344 pack_report(object *obj, int print_message, char *message)
345 {
346 /* Notify the user */
347
348 if (print_message)
349 {
350 if (!terse)
351 addmsg(message);
352
353 msg("(%c%c) %s.", obj->o_type, print_letters[get_ident(obj)],
354 inv_name(obj, !terse));
355 }
356
357 if (obj->o_type == ARTIFACT)
358 {
359 has_artifact |= (1 << obj->o_which);
360 picked_artifact |= (1 << obj->o_which);
361
362 if (!(obj->ar_flags & ISUSED))
363 {
364 obj->ar_flags |= ISUSED;
365 pstats.s_exp += arts[obj->o_which].ar_worth / 10;
366 check_level();
367 }
368 }
369
370 updpack();
371
372 return;
373 }
374
375 /*
376 inventory()
377 list what is in the pack
378 */
379
380 void
381 inventory(struct linked_list *container, int type)
382 {
383 int cnt;