rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

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}