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