Neale Pickett
·
2011-10-13
packet.c
1#include <curses.h>
2#include <ctype.h>
3#include "netprot.h"
4
5/*
6 * Routines to deal with the pack
7 *
8 * @(#)packet.c 4.40 (Berkeley) 02/05/99
9 */
10
11/*
12 * add_pack:
13 * Pick up an object and add it to the pack. If the argument is
14 * non-null use it as the linked_list pointer instead of gettting
15 * it off the ground.
16 */
17void
18add_pack(THING *obj, bool silent)
19{
20 THING *op, *lp;
21 bool from_floor;
22
23 from_floor = FALSE;
24 if (obj == NULL)
25 {
26 if ((obj = find_obj(Hero.y, Hero.x)) == NULL)
27 return;
28 from_floor = TRUE;
29 }
30
31 /*
32 * Check for and deal with scare monster scrolls
33 */
34 if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
35 if (obj->o_flags & ISFOUND)
36 {
37 detach(Lvl_obj, obj);
38 mvaddch(Hero.y, Hero.x, floor_ch());
39 chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
40 discard(obj);
41 msg("the scroll turns to dust as you pick it up");
42 return;
43 }
44
45 if (Pack == NULL)
46 {
47 Pack = obj;
48 obj->o_packch = pack_char();
49 Inpack++;
50 }
51 else
52 {
53 lp = NULL;
54 for (op = Pack; op != NULL; op = next(op))
55 {
56 if (op->o_type != obj->o_type)
57 lp = op;
58 else
59 {
60 while (op->o_type == obj->o_type && op->o_which != obj->o_which)
61 {
62 lp = op;
63 if (next(op) == NULL)
64 break;
65 else
66 op = next(op);
67 }
68 if (op->o_type == obj->o_type && op->o_which == obj->o_which)
69 if (ISMULT(op->o_type))
70 {
71 if (!pack_room(from_floor, obj))
72 return;
73 op->o_count++;
74dump_it:
75 discard(obj);
76 obj = op;
77 lp = NULL;
78 goto out;
79 }
80 else if (obj->o_group)
81 {
82 lp = op;
83 while (op->o_type == obj->o_type
84 && op->o_which == obj->o_which
85 && op->o_group != obj->o_group)
86 {
87 lp = op;
88 if (next(op) == NULL)
89 break;
90 else
91 op = next(op);
92 }
93 if (op->o_type == obj->o_type
94 && op->o_which == obj->o_which
95 && op->o_group == obj->o_group)
96 {
97 op->o_count += obj->o_count;
98 Inpack--;
99 if (!pack_room(from_floor, obj))
100 return;
101 goto dump_it;
102 }
103 }
104 else
105 lp = op;
106out:
107 break;
108 }
109 }
110
111 if (lp != NULL)
112 if (!pack_room(from_floor, obj))
113 return;
114 else
115 {
116 obj->o_packch = pack_char();
117 next(obj) = next(lp);
118 prev(obj) = lp;
119 if (next(lp) != NULL)
120 prev(next(lp)) = obj;
121 next(lp) = obj;
122 }
123 }
124
125 obj->o_flags |= ISFOUND;
126
127 /*
128 * If this was the object of something's desire, that monster will
129 * get mad and run at the hero.
130 */
131 for (op = Mlist; op != NULL; op = next(op))
132 if (op->t_dest = &obj->o_pos)
133 op->t_dest = &Hero;
134
135 if (obj->o_type == AMULET)
136 Amulet = TRUE;
137 /*
138 * Notify the user
139 */
140 if (!silent)
141 {
142 if (!Terse)
143 addmsg("you now have ");
144 msg("%s (%c)", inv_name(obj, !Terse), obj->o_packch);
145 }
146}
147
148/*
149 * pack_room:
150 * See if there's room in the pack. If not, print out an
151 * appropriate message
152 */
153bool
154pack_room(bool from_floor, THING *obj)
155{
156 if (++Inpack > MAXPACK)
157 {
158 if (!Terse)
159 addmsg("there's ");
160 addmsg("no room");
161 if (!Terse)
162 addmsg(" in your pack");
163 endmsg();
164 if (from_floor)
165 move_msg(obj);
166 Inpack = MAXPACK;
167 return FALSE;
168 }
169
170 if (from_floor)
171 {
172 detach(Lvl_obj, obj);
173 mvaddch(Hero.y, Hero.x, floor_ch());
174 chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
175 }
176
177 return TRUE;
178}
179
180/*
181 * leave_pack:
182 * Take an item out of the pack
183 */
184THING *
185leave_pack(THING *obj, bool newobj, bool all)
186{
187 THING *nobj;
188
189 Inpack--;
190 nobj = obj;
191 if (obj->o_count > 1 && !all)
192 {
193 Last_pick = obj;
194 obj->o_count--;
195 if (obj->o_group)
196 Inpack++;
197 if (newobj)
198 {
199 nobj = new_item();
200 *nobj = *obj;
201 next(nobj) = NULL;
202 prev(nobj) = NULL;
203 nobj->o_count = 1;
204 }
205 }
206 else
207 {
208 Last_pick = NULL;
209 Pack_used[obj->o_packch - 'a'] = FALSE;
210 detach(Pack, obj);
211 }
212 return nobj;
213}
214
215/*
216 * pack_char:
217 * Return the next unused pack character.
218 */
219char
220pack_char(void)
221{
222 bool *bp;
223
224 for (bp = Pack_used; *bp; bp++)
225 continue;
226 *bp = TRUE;
227 return (bp - Pack_used) + 'a';
228}
229
230/*
231 * inventory:
232 * List what is in the pack. Return TRUE if there is something of
233 * the given type.
234 */
235bool
236inventory(THING *list, int type)
237{
238 static char inv_temp[MAXSTR];
239
240 N_objs = 0;
241 for (; list != NULL; list = next(list))
242 {
243 if (type && type != list->o_type && !(type == CALLABLE &&
244 list->o_type != FOOD && list->o_type != AMULET) &&
245 !(type == R_OR_S && (list->o_type == RING || list->o_type == STICK)))
246 continue;
247 N_objs++;
248#ifdef MASTER
249 if (!list->o_packch)
250 strcpy(inv_temp, "%s");
251 else
252#endif
253 sprintf(inv_temp, "%c) %%s", list->o_packch);
254 Msg_esc = TRUE;
255 if (add_line(inv_temp, inv_name(list, FALSE)) == ESCAPE)
256 {
257 Msg_esc = FALSE;
258 msg("");
259 return TRUE;
260 }
261 Msg_esc = FALSE;
262 }
263 if (N_objs == 0)
264 {
265 if (Terse)
266 msg(type == 0 ? "empty handed" :
267 "nothing appropriate");
268 else
269 msg(type == 0 ? "you are empty handed" :
270 "you don't have anything appropriate");
271 return FALSE;
272 }
273 end_line();
274 return TRUE;
275}
276
277/*
278 * pick_up:
279 * Add something to characters pack.
280 */
281void
282pick_up(char ch)
283{
284 THING *obj;
285
286 if (on(Player, ISLEVIT))
287 return;
288
289 obj = find_obj(Hero.y, Hero.x);
290 if (Move_on)
291 move_msg(obj);
292 else
293 switch (ch)
294 {
295 case GOLD:
296 if (obj == NULL)
297 return;
298 money(obj->o_goldval);
299 detach(Lvl_obj, obj);
300 discard(obj);
301 Proom->r_goldval = 0;
302 break;
303 default:
304#ifdef MASTER
305 debug("Where did you pick a '%s' up???", unctrl(ch));
306#endif
307 case ARMOR:
308 case POTION:
309 case FOOD:
310 case WEAPON:
311 case SCROLL:
312 case AMULET:
313 case RING:
314 case STICK:
315 add_pack((THING *) NULL, FALSE);
316 break;
317 }
318}
319
320/*
321 * move_msg:
322 * Print out the message if you are just moving onto an object
323 */
324void
325move_msg(THING *obj)
326{
327 if (!Terse)
328 addmsg("you ");
329 msg("moved onto %s", inv_name(obj, TRUE));
330}
331
332/*
333 * picky_inven:
334 * Allow player to inventory a single item
335 */
336void
337picky_inven(void)
338{
339 THING *obj;
340 char mch;
341
342 if (Pack == NULL)
343 msg("you aren't carrying anything");
344 else if (next(Pack) == NULL)
345 msg("a) %s", inv_name(Pack, FALSE));
346 else
347 {
348 msg(Terse ? "item: " : "which item do you wish to inventory: ");
349 Mpos = 0;
350 if ((mch = readchar()) == ESCAPE)
351 {
352 msg("");
353 return;
354 }
355 for (obj = Pack; obj != NULL; obj = next(obj))
356 if (mch == obj->o_packch)
357 {
358 msg("%c) %s", mch, inv_name(obj, FALSE));
359 return;
360 }
361 msg("'%s' not in pack", unctrl(mch));
362 }
363}
364
365/*
366 * get_item:
367 * Pick something out of a pack for a purpose
368 */
369THING *
370get_item(char *purpose, int type)
371{
372 THING *obj;
373 char ch;
374
375 if (Pack == NULL)
376 msg("you aren't carrying anything");
377 else if (Again)
378 if (Last_pick)
379 return Last_pick;
380 else
381 msg("you ran out");
382 else
383 {
384 for (;;)
385 {
386 if (!Terse)
387 addmsg("which object do you want to ");
388 addmsg(purpose);
389 if (Terse)
390 addmsg(" what");
391 msg("? (* for list): ");
392 ch = readchar();
393 Mpos = 0;
394 /*
395 * Give the poor player a chance to abort the command
396 */
397 if (ch == ESCAPE)
398 {
399 reset_last();
400 After = FALSE;
401 msg("");
402 return NULL;
403 }
404 N_objs = 1; /* normal case: person types one char */
405 if (ch == '*')
406 {
407 Mpos = 0;
408 if (inventory(Pack, type) == 0)
409 {
410 After = FALSE;
411 return NULL;
412 }
413 continue;
414 }
415 for (obj = Pack; obj != NULL; obj = next(obj))
416 if (obj->o_packch == ch)
417 break;
418 if (obj == NULL)
419 {
420 msg("that's not a valid item");
421 continue;
422 }
423 else
424 return obj;
425 }
426 }
427 return NULL;
428}
429
430/*
431 * money:
432 * Add or subtract gold from the pack
433 */
434void
435money(int value)
436{
437 Purse += value;
438 mvaddch(Hero.y, Hero.x, floor_ch());
439 chat(Hero.y, Hero.x) = (Proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
440 if (value > 0)
441 {
442 if (!Terse)
443 addmsg("you found ");
444 msg("%d gold pieces", value);
445 }
446}
447
448/*
449 * floor_ch:
450 * Return the appropriate floor character for her room
451 */
452char
453floor_ch(void)
454{
455 if (Proom->r_flags & ISGONE)
456 return PASSAGE;
457 return (show_floor() ? FLOOR : ' ');
458}
459
460/*
461 * floor_at:
462 * Return the character at hero's position, taking See_floor
463 * into account
464 */
465char
466floor_at(void)
467{
468 char ch;
469
470 ch = chat(Hero.y, Hero.x);
471 if (ch == FLOOR)
472 ch = floor_ch();
473 return ch;
474}
475
476/*
477 * reset_last:
478 * Reset the last command when the current one is aborted
479 */
480void
481reset_last(void)
482{
483 Last_comm = L_last_comm;
484 Last_dir = L_last_dir;
485 Last_pick = L_last_pick;
486}