Mercurial > hg > early-roguelike
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; | |