1 #include "rogue.h" 2 #include "curses.h" 3 4 /* 5 * Routines to deal with the pack 6 * 7 * pack.c 1.4 (A.I. Design) 12/14/84 8 */ 9 10 THING * 11 pack_obj(ch, chp) 12 byte ch, *chp; 13 { 14 register THING *obj; 15 register byte och; 16 17 for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++) 18 if (ch == och) 19 return obj; 20 *chp = och; 21 return NULL; 22 } 23 24 /* 25 * add_pack: 26 * Pick up an object and add it to the pack. If the argument is 27 * non-null use it as the linked_list pointer instead of gettting 28 * it off the ground. 29 */ 30 add_pack(obj, silent) 31 register THING *obj; 32 bool silent; 33 { 34 register THING *op, *lp; 35 register bool exact, from_floor; 36 register byte floor; 37 38 if (obj == NULL) 39 { 40 from_floor = TRUE; 41 if ((obj = find_obj(hero.y, hero.x)) == NULL) 42 return; 43 } 44 else 45 from_floor = FALSE; 46 /* 47 * Link it into the pack. Search the pack for a object of similar type 48 * if there isn't one, stuff it at the beginning, if there is, look for one 49 * that is exactly the same and just increment the count if there is. 50 * Food is always put at the beginning for ease of access, but it 51 * is not ordered so that you can't tell good food from bad. First check 52 * to see if there is something in the same group and if there is then 53 * increment the count. 54 */ 55 floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; 56 if (obj->o_group) 57 { 58 for (op = pack; op != NULL; op = next(op)) 59 { 60 if (op->o_group == obj->o_group) 61 { 62 /* 63 * Put it in the pack and notify the user 64 */ 65 op->o_count += obj->o_count; 66 if (from_floor) 67 { 68 detach(lvl_obj, obj); 69 mvaddch(hero.y, hero.x, floor); 70 chat(hero.y, hero.x) = floor; 71 } 72 discard(obj); 73 obj = op; 74 goto picked_up; 75 } 76 } 77 } 78 /* 79 * Check if there is room 80 */ 81 if (inpack >= MAXPACK-1) 82 { 83 msg("you can't carry anything else"); 84 return; 85 } 86 /* 87 * Check for and deal with scare monster scrolls 88 */ 89 if (obj->o_type == SCROLL && obj->o_which == S_SCARE) 90 if (obj->o_flags & ISFOUND) 91 { 92 detach(lvl_obj, obj); 93 mvaddch(hero.y, hero.x, floor); 94 chat(hero.y, hero.x) = floor; 95 msg("the scroll turns to dust%s.", noterse(" as you pick it up")); 96 return; 97 } 98 else 99 obj->o_flags |= ISFOUND; 100 101 inpack++; 102 if (from_floor) 103 { 104 detach(lvl_obj, obj); 105 mvaddch(hero.y, hero.x, floor); 106 chat(hero.y, hero.x) = floor; 107 } 108 /* 109 * Search for an object of the same type 110 */ 111 exact = FALSE; 112 for (op = pack; op != NULL; op = next(op)) 113 if (obj->o_type == op->o_type) 114 break; 115 if (op == NULL) 116 { 117 /* 118 * Put it at the end of the pack since it is a new type 119 */ 120 for (op = pack; op != NULL; op = next(op)) 121 { 122 if (op->o_type != FOOD) 123 break; 124 lp = op; 125 } 126 } 127 else 128 { 129 /* 130 * Search for an object which is exactly the same 131 */ 132 while (op->o_type == obj->o_type) 133 { 134 if (op->o_which == obj->o_which) 135 { 136 exact = TRUE; 137 break; 138 } 139 lp = op; 140 if ((op = next(op)) == NULL) 141 break; 142 } 143 } 144 if (op == NULL) 145 { 146 /* 147 * Didn't find an exact match, just stick it here 148 */ 149 if (pack == NULL) 150 pack = obj; 151 else 152 { 153 lp->l_next = obj; 154 obj->l_prev = lp; 155 obj->l_next = NULL; 156 } 157 } 158 else 159 { 160 /* 161 * If we found an exact match. If it is a potion, food, or a 162 * scroll, increase the count, otherwise put it with its clones. 163 */ 164 if (exact && ISMULT(obj->o_type)) 165 { 166 op->o_count++; 167 discard(obj); 168 obj = op; 169 goto picked_up; 170 } 171 if ((obj->l_prev = prev(op)) != NULL) 172 obj->l_prev->l_next = obj; 173 else 174 pack = obj; 175 obj->l_next = op; 176 op->l_prev = obj; 177 } 178 picked_up: 179 /* 180 * If this was the object of something's desire, that monster will 181 * get mad and run at the hero 182 */ 183 for (op = mlist; op != NULL; op = next(op)) 184 /* 185 * compiler bug: jll : 2-7-83 186 * It is stupid because it thinks the obj... is not an lvalue 187 * this may be true since there is no structure assignments, 188 * but still it should let you have the address??!! 189 * 190 if (&obj->_o._o_pos == op->t_dest) 191 * 192 * the following should do the same 193 */ 194 if ((op->t_dest->x == obj->o_pos.x) && (op->t_dest->y == obj->o_pos.y)) 195 op->t_dest = &hero; 196 197 if (obj->o_type == AMULET) 198 { 199 amulet = TRUE; 200 saw_amulet = TRUE; 201 } 202 /* 203 * Notify the user 204 */ 205 if (!silent) 206 msg("%s%s (%c)",noterse("you now have "), 207 inv_name(obj, TRUE), pack_char(obj)); 208 } 209 210 /* 211 * inventory: 212 * List what is in the pack 213 */ 214 inventory(list, type, lstr) 215 THING *list; 216 int type; 217 char *lstr; 218 { 219 register byte ch; 220 register int n_objs; 221 char inv_temp[MAXSTR]; 222 223 n_objs = 0; 224 for (ch = 'a'; list != NULL; ch++, list = next(list)) 225 { 226 /* 227 * Don't print this one if: 228 * the type doesn't match the type we were passed AND 229 * it isn't a callable type AND 230 * it isn't a zappable weapon 231 */ 232 if (type && type != list->o_type && !(type == CALLABLE && 233 (list->o_type == SCROLL || list->o_type == POTION || 234 list->o_type == RING || list->o_type == STICK)) && 235 !(type == WEAPON && list->o_type == POTION) && 236 !(type == STICK && list->o_enemy && list->o_charges)) 237 continue; 238 n_objs++; 239 sprintf(inv_temp, "%c) %%s", ch); 240 add_line(lstr, inv_temp, inv_name(list, FALSE)); 241 } 242 if (n_objs == 0) 243 { 244 msg(type == 0 ? "you are empty handed" : 245 "you don't have anything appropriate"); 246 return FALSE; 247 } 248 return(end_line(lstr)); 249 } 250 251 /* 252 * pick_up: 253 * Add something to characters pack. 254 */ 255 pick_up(ch) 256 byte ch; 257 { 258 register THING *obj; 259 260 switch (ch) 261 { 262 case GOLD: 263 if ((obj = find_obj(hero.y, hero.x)) == NULL) 264 return; 265 money(obj->o_goldval); 266 detach(lvl_obj, obj); 267 discard(obj); 268 proom->r_goldval = 0; 269 break; 270 default: 271 case ARMOR: 272 case POTION: 273 case FOOD: 274 case WEAPON: 275 case SCROLL: 276 case AMULET: 277 case RING: 278 case STICK: 279 add_pack(NULL, FALSE); 280 break; 281 } 282 } 283 284 /* 285 * get_item: 286 * Pick something out of a pack for a purpose 287 */ 288 THING * 289 get_item(purpose, type) 290 char *purpose; 291 int type; 292 { 293 register THING *obj; 294 register byte ch; 295 byte och; 296 static byte lch; 297 static THING *wasthing = NULL; 298 byte gi_state; /* get item sub state */ 299 int once_only = FALSE; 300 301 if (((!strncmp(s_menu,"sel",3) && strcmp(purpose,"eat") 302 && strcmp(purpose,"drop"))) || !strcmp(s_menu,"on")) 303 once_only = TRUE; 304 305 gi_state = again; 306 if (pack == NULL) 307 msg("you aren't carrying anything"); 308 else { 309 ch = lch; 310 for (;;) { 311 /* 312 * if we are doing something AGAIN, and the pack hasn't 313 * changed then don't ask just give him the same thing 314 * he got on the last command. 315 */ 316 if (gi_state && wasthing == pack_obj(ch, &och)) 317 goto skip; 318 if (once_only) { 319 ch = '*'; 320 goto skip; 321 } 322 if (!terse && !expert) 323 addmsg("which object do you want to "); 324 msg("%s? (* for list): ",purpose); 325 /* 326 * ignore any alt characters that may be typed 327 */ 328 ch = readchar(); 329 skip: 330 mpos = 0; 331 gi_state = FALSE; 332 once_only = FALSE; 333 if (ch == '*') { 334 if ((ch = inventory(pack, type, purpose)) == 0) { 335 after = FALSE; 336 return NULL; 337 } 338 if (ch == ' ') 339 continue; 340 lch = ch; 341 } 342 /* 343 * Give the poor player a chance to abort the command 344 */ 345 if (ch == ESCAPE) { 346 after = FALSE; 347 msg(""); 348 return NULL; 349 } 350 if ((obj = pack_obj(ch, &och)) == NULL) { 351 ifterse1("range is 'a' to '%c'","please specify a letter between 'a' and '%c'", och-1); 352 continue; 353 } else { 354 /* 355 * If you find an object reset flag because 356 * you really don't know if the object he is getting 357 * is going to change the pack. If he detaches the 358 * thing from the pack later this flag will get set. 359 */ 360 if (strcmp(purpose, "identify")) { 361 lch = ch; 362 wasthing = obj; 363 } 364 return obj; 365 } 366 } 367 } 368 return NULL; 369 } 370 371 /* 372 * pack_char: 373 * Return which character would address a pack object 374 */ 375 pack_char(obj) 376 register THING *obj; 377 { 378 register THING *item; 379 register byte c; 380 381 c = 'a'; 382 for (item = pack; item != NULL; item = next(item)) 383 if (item == obj) 384 return c; 385 else 386 c++; 387 return '?'; 388 } 389 390 /* 391 * money: 392 * Add or subtract gold from the pack 393 */ 394 money(value) 395 register int value; 396 { 397 register byte floor; 398 399 floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; 400 purse += value; 401 mvaddch(hero.y, hero.x, floor); 402 chat(hero.y, hero.x) = floor; 403 if (value > 0) 404 { 405 msg("you found %d gold pieces", value); 406 } 407 } 408 ÿ