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