comparison xrogue/pack.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 pack.c - Routines to deal with the pack.
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 #include <curses.h>
20 #include <ctype.h>
21 #include "rogue.h"
22
23 /*
24 * add_pack:
25 * Pick up an object and add it to the pack. If the argument is non-null
26 * use it as the linked_list pointer instead of gettting it off the ground.
27 */
28
29 bool
30 add_pack(item, silent)
31 register struct linked_list *item;
32 bool silent;
33 {
34 register struct linked_list *ip, *lp = NULL, *ap;
35 register struct object *obj, *op = NULL;
36 register bool exact, from_floor;
37 bool giveflag = 0;
38 static long cleric = C_CLERIC,
39 monk = C_MONK,
40 magician = C_MAGICIAN,
41 assassin = C_ASSASSIN,
42 druid = C_DRUID,
43 thief = C_THIEF,
44 fighter = C_FIGHTER,
45 ranger = C_RANGER,
46 paladin = C_PALADIN;
47
48 if (item == NULL)
49 {
50 from_floor = TRUE;
51 if ((item = find_obj(hero.y, hero.x)) == NULL)
52 return(FALSE);
53 }
54 else
55 from_floor = FALSE;
56 obj = OBJPTR(item);
57 /*
58 * If it is gold, just add its value to rogue's purse and get rid
59 * of it.
60 */
61 if (obj->o_type == GOLD) {
62 register struct linked_list *mitem;
63 register struct thing *tp;
64
65 if (!silent) {
66 if (!terse) addmsg("You found ");
67 msg("%d gold pieces.", obj->o_count);
68 }
69
70 /* First make sure no greedy monster is after this gold.
71 * If so, make the monster run after the rogue instead.
72 */
73 for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
74 tp = THINGPTR(mitem);
75 if (tp->t_dest == &obj->o_pos) tp->t_dest = &hero;
76 }
77
78 purse += obj->o_count;
79 if (from_floor) {
80 detach(lvl_obj, item);
81 if ((ap = find_obj(hero.y, hero.x)) == NULL)
82 mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
83 else
84 mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
85 }
86 o_discard(item);
87 return(TRUE);
88 }
89
90 /*
91 * see if he can carry any more weight
92 */
93 if (itemweight(obj) + pstats.s_pack > pstats.s_carry) {
94 msg("Too much for you to carry.");
95 return FALSE;
96 }
97 /*
98 * Link it into the pack. Search the pack for a object of similar type
99 * if there isn't one, stuff it at the beginning, if there is, look for one
100 * that is exactly the same and just increment the count if there is.
101 * it that. Food is always put at the beginning for ease of access, but
102 * is not ordered so that you can't tell good food from bad. First check
103 * to see if there is something in thr same group and if there is then
104 * increment the count.
105 */
106 if (obj->o_group)
107 {
108 for (ip = pack; ip != NULL; ip = next(ip))
109 {
110 op = OBJPTR(ip);
111 if (op->o_group == obj->o_group)
112 {
113 /*
114 * Put it in the pack and notify the user
115 */
116 op->o_count += obj->o_count;
117 if (from_floor)
118 {
119 detach(lvl_obj, item);
120 if ((ap = find_obj(hero.y, hero.x)) == NULL)
121 mvaddch(hero.y,hero.x,
122 (roomin(&hero)==NULL ? PASSAGE : FLOOR));
123 else
124 mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
125 }
126 o_discard(item);
127 item = ip;
128 goto picked_up;
129 }
130 }
131 }
132
133 /*
134 * Check for and deal with scare monster scrolls
135 */
136 if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
137 if (obj->o_flags & ISCURSED)
138 {
139 msg("The scroll turns to dust as you pick it up.");
140 detach(lvl_obj, item);
141 if ((ap = find_obj(hero.y, hero.x)) == NULL)
142 mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
143 else
144 mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
145 return(TRUE);
146 }
147
148 /*
149 * Search for an object of the same type
150 */
151 exact = FALSE;
152 for (ip = pack; ip != NULL; ip = next(ip))
153 {
154 op = OBJPTR(ip);
155 if (obj->o_type == op->o_type)
156 break;
157 }
158 if (ip == NULL)
159 {
160 /*
161 * Put it at the end of the pack since it is a new type
162 */
163 for (ip = pack; ip != NULL; ip = next(ip))
164 {
165 op = OBJPTR(ip);
166 if (op->o_type != FOOD)
167 break;
168 lp = ip;
169 }
170 }
171 else
172 {
173 /*
174 * Search for an object which is exactly the same
175 */
176 while (ip != NULL && op->o_type == obj->o_type)
177 {
178 if (op->o_which == obj->o_which)
179 {
180 exact = TRUE;
181 break;
182 }
183 lp = ip;
184 if ((ip = next(ip)) == NULL)
185 break;
186 op = OBJPTR(ip);
187 }
188 }
189 /*
190 * Check if there is room
191 */
192 if (ip == NULL || !exact || !ISMULT(obj->o_type)) {
193 if (inpack == MAXPACK-1) {
194 msg(terse ? "No room." : "You can't carry anything else.");
195 return(FALSE);
196 }
197 }
198 inpack++;
199 if (from_floor)
200 {
201 detach(lvl_obj, item);
202 if ((ap = find_obj(hero.y, hero.x)) == NULL)
203 mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
204 else
205 mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
206 }
207 if (ip == NULL)
208 {
209 /*
210 * Didn't find an exact match, just stick it here
211 */
212 if (pack == NULL)
213 pack = item;
214 else
215 {
216 lp->l_next = item;
217 item->l_prev = lp;
218 item->l_next = NULL;
219 }
220 }
221 else
222 {
223 /*
224 * If we found an exact match. If it is food,
225 * increase the count, otherwise put it with its clones.
226 */
227 if (exact && ISMULT(obj->o_type))
228 {
229 op->o_count += obj->o_count;
230 inpack--; /* adjust for previous addition */
231 o_discard(item);
232 item = ip;
233 goto picked_up;
234 }
235 if ((item->l_prev = prev(ip)) != NULL)
236 item->l_prev->l_next = item;
237 else
238 pack = item;
239 item->l_next = ip;
240 ip->l_prev = item;
241 }
242 picked_up:
243 /*
244 * Notify the user
245 */
246 obj = OBJPTR(item);
247 if (!silent)
248 {
249 if (!terse)
250 addmsg("You now have ");
251 msg("%s (%c)", inv_name(obj, !terse), pack_char(pack, obj));
252 }
253
254 /* Relics do strange things when you pick them up */
255 if (obj->o_type == RELIC) {
256 switch (obj->o_which) {
257 /* the ankh of Heil gives you prayers */
258 case HEIL_ANKH:
259 msg("The ankh welds itself into your hand. ");
260 if (player.t_ctype != C_CLERIC && player.t_ctype != C_PALADIN)
261 fuse(prayer_recovery, (VOID *)NULL, SPELLTIME, AFTER);
262 /* start a fuse to change player into a paladin */
263 if (quest_item != HEIL_ANKH) {
264 msg("You hear a strange, distant hypnotic calling... ");
265 if (player.t_ctype != C_PALADIN && obj->o_which ==HEIL_ANKH)
266 fuse(changeclass, &paladin, roll(8, 8), AFTER);
267 }
268
269 /* A cloak must be worn. */
270 when EMORI_CLOAK:
271 if (cur_armor != NULL || cur_misc[WEAR_CLOAK]) {
272 msg("The cloak insists you remove your current garments.");
273 if (!dropcheck(cur_armor != NULL ? cur_armor
274 : cur_misc[WEAR_CLOAK])) {
275 pstats.s_hpt = -1;
276 msg("The cloak constricts around you...");
277 msg("It draws your life force from you!!! --More--");
278 wait_for(' ');
279 death(D_RELIC);
280 }
281 }
282 if (obj->o_charges < 0) /* should never happen, but.... */
283 obj->o_charges = 0;
284 if (obj->o_charges == 0)
285 fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
286 /* start a fuse to change player into a monk */
287 if (quest_item != EMORI_CLOAK) {
288 msg("You suddenly become calm and quiet. ");
289 if (player.t_ctype != C_MONK && obj->o_which == EMORI_CLOAK)
290 fuse(changeclass, &monk, roll(8, 8), AFTER);
291 }
292
293 /* The amulet must be worn. */
294 when STONEBONES_AMULET:
295 case YENDOR_AMULET:
296 if (cur_misc[WEAR_JEWEL] || cur_relic[STONEBONES_AMULET] ||
297 cur_relic[YENDOR_AMULET]) {
298 msg("You have an urge to remove your current amulet.");
299 }
300 if((cur_misc[WEAR_JEWEL] && !dropcheck(cur_misc[WEAR_JEWEL])) ||
301 cur_relic[STONEBONES_AMULET] || cur_relic[YENDOR_AMULET]) {
302 pstats.s_hpt = -1;
303 msg("The %s begins pulsating... ",inv_name(obj, TRUE));
304 msg("It fades completely away! --More--");
305 wait_for(' ');
306 death(D_RELIC);
307 }
308 msg("The %s welds itself into your chest. ",inv_name(obj,TRUE));
309 /* start a fuse to change into a magician */
310 if (quest_item != STONEBONES_AMULET) {
311 if (player.t_ctype != C_MAGICIAN &&
312 obj->o_which == STONEBONES_AMULET) {
313 msg("You sense approaching etheric forces... ");
314 fuse(changeclass, &magician, roll(8, 8), AFTER);
315 }
316 }
317
318 /* The eye is now inserted in forehead */
319 when EYE_VECNA:
320 msg("The eye forces itself into your forehead! ");
321 pstats.s_hpt -= (rnd(80)+21);
322 if (pstats.s_hpt <= 0) {
323 pstats.s_hpt = -1;
324 msg ("The pain is too much for you to bear! --More--");
325 wait_for(' ');
326 death(D_RELIC);
327 }
328 waste_time();
329 msg("The excruciating pain slowly turns into a dull throb.");
330 /* start a fuse to change player into an assassin */
331 if (quest_item != EYE_VECNA) {
332 msg("Your blood rushes and you begin to sweat profusely... ");
333 if (player.t_ctype != C_ASSASSIN && obj->o_which == EYE_VECNA)
334 fuse(changeclass, &assassin, roll(8, 8), AFTER);
335 }
336
337 when QUILL_NAGROM:
338 fuse(quill_charge,(VOID *)NULL, 8, AFTER);
339 /* start a fuse to change player into a druid */
340 if (quest_item != QUILL_NAGROM) {
341 msg("You begin to see things differently... ");
342 if (player.t_ctype != C_DRUID && obj->o_which == QUILL_NAGROM)
343 fuse(changeclass, &druid, roll(8, 8), AFTER);
344 }
345
346 /* Weapons will insist on being wielded. */
347 when MUSTY_DAGGER:
348 case HRUGGEK_MSTAR:
349 case YEENOGHU_FLAIL:
350 case AXE_AKLAD:
351 /* set a daemon to eat gold for daggers and axe */
352 if (obj->o_which == MUSTY_DAGGER || obj->o_which == AXE_AKLAD) {
353 if (purse > 0) msg("Your purse feels lighter! ");
354 else purse = 1; /* fudge to get right msg from eat_gold() */
355