Mercurial > hg > early-roguelike
comparison rogue4/pack.c @ 12:9535a08ddc39
Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
| author | edwarj4 |
|---|---|
| date | Sat, 24 Oct 2009 16:52:52 +0000 |
| parents | |
| children | 1b73a8641b37 |
comparison
equal
deleted
inserted
replaced
| 11:949d558c2162 | 12:9535a08ddc39 |
|---|---|
| 1 /* | |
| 2 * Routines to deal with the pack | |
| 3 * | |
| 4 * @(#)pack.c 4.15 (Berkeley) 4/6/82 | |
| 5 * | |
| 6 * Rogue: Exploring the Dungeons of Doom | |
| 7 * Copyright (C) 1980, 1981, 1982 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 * update_mdest: | |
| 19 * Called after picking up an object, before discarding it. | |
| 20 * If this was the object of something's desire, that monster will | |
| 21 * get mad and run at the hero | |
| 22 */ | |
| 23 update_mdest(obj) | |
| 24 register THING *obj; | |
| 25 { | |
| 26 register THING *mp; | |
| 27 | |
| 28 for (mp = mlist; mp != NULL; mp = next(mp)) | |
| 29 if (mp->t_dest == &obj->o_pos) | |
| 30 mp->t_dest = &hero; | |
| 31 } | |
| 32 | |
| 33 /* | |
| 34 * add_pack: | |
| 35 * Pick up an object and add it to the pack. If the argument is | |
| 36 * non-null use it as the linked_list pointer instead of gettting | |
| 37 * it off the ground. | |
| 38 */ | |
| 39 add_pack(obj, silent) | |
| 40 register THING *obj; | |
| 41 bool silent; | |
| 42 { | |
| 43 register THING *op, *lp = NULL; | |
| 44 register bool exact, from_floor; | |
| 45 register char floor; | |
| 46 int discarded = 0; | |
| 47 | |
| 48 if (obj == NULL) | |
| 49 { | |
| 50 from_floor = TRUE; | |
| 51 if ((obj = find_obj(hero.y, hero.x)) == NULL) | |
| 52 return; | |
| 53 } | |
| 54 else | |
| 55 from_floor = FALSE; | |
| 56 /* | |
| 57 * Link it into the pack. Search the pack for a object of similar type | |
| 58 * if there isn't one, stuff it at the beginning, if there is, look for one | |
| 59 * that is exactly the same and just increment the count if there is. | |
| 60 * it that. Food is always put at the beginning for ease of access, but | |
| 61 * is not ordered so that you can't tell good food from bad. First check | |
| 62 * to see if there is something in thr same group and if there is then | |
| 63 * increment the count. | |
| 64 */ | |
| 65 /* floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */ | |
| 66 if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; | |
| 67 else floor = FLOOR; | |
| 68 if (obj->o_group) | |
| 69 { | |
| 70 for (op = pack; op != NULL; op = next(op)) | |
| 71 { | |
| 72 if (op->o_group == obj->o_group) | |
| 73 { | |
| 74 /* | |
| 75 * Put it in the pack and notify the user | |
| 76 */ | |
| 77 op->o_count++; | |
| 78 if (from_floor) | |
| 79 { | |
| 80 detach(lvl_obj, obj); | |
| 81 mvaddch(hero.y, hero.x, floor); | |
| 82 chat(hero.y, hero.x) = floor; | |
| 83 } | |
| 84 update_mdest(obj); | |
| 85 discard(obj); | |
| 86 obj = op; | |
| 87 discarded = 1; | |
| 88 goto picked_up; | |
| 89 } | |
| 90 } | |
| 91 } | |
| 92 /* | |
| 93 * Check if there is room | |
| 94 */ | |
| 95 if (inpack == MAXPACK-1) | |
| 96 { | |
| 97 msg("you can't carry anything else"); | |
| 98 return; | |
| 99 } | |
| 100 /* | |
| 101 * Check for and deal with scare monster scrolls | |
| 102 */ | |
| 103 if (obj->o_type == SCROLL && obj->o_which == S_SCARE) | |
| 104 if (obj->o_flags & ISFOUND) | |
| 105 { | |
| 106 detach(lvl_obj, obj); | |
| 107 mvaddch(hero.y, hero.x, floor); | |
| 108 chat(hero.y, hero.x) = floor; | |
| 109 msg("the scroll turns to dust as you pick it up"); | |
| 110 return; | |
| 111 } | |
| 112 else | |
| 113 obj->o_flags |= ISFOUND; | |
| 114 | |
| 115 inpack++; | |
| 116 if (from_floor) | |
| 117 { | |
| 118 detach(lvl_obj, obj); | |
| 119 mvaddch(hero.y, hero.x, floor); | |
| 120 chat(hero.y, hero.x) = floor; | |
| 121 } | |
| 122 /* | |
| 123 * Search for an object of the same type | |
| 124 */ | |
| 125 exact = FALSE; | |
| 126 for (op = pack; op != NULL; op = next(op)) | |
| 127 if (obj->o_type == op->o_type) | |
| 128 break; | |
| 129 if (op == NULL) | |
| 130 { | |
| 131 /* | |
| 132 * Put it at the end of the pack since it is a new type | |
| 133 */ | |
| 134 for (op = pack; op != NULL; op = next(op)) | |
| 135 { | |
| 136 if (op->o_type != FOOD) | |
| 137 break; | |
| 138 lp = op; | |
| 139 } | |
| 140 } | |
| 141 else | |
| 142 { | |
| 143 /* | |
| 144 * Search for an object which is exactly the same | |
| 145 */ | |
| 146 while (op->o_type == obj->o_type) | |
| 147 { | |
| 148 if (op->o_which == obj->o_which) | |
| 149 { | |
| 150 exact = TRUE; | |
| 151 break; | |
| 152 } | |
| 153 lp = op; | |
| 154 if ((op = next(op)) == NULL) | |
| 155 break; | |
| 156 } | |
| 157 } | |
| 158 if (op == NULL) | |
| 159 { | |
| 160 /* | |
| 161 * Didn't find an exact match, just stick it here | |
| 162 */ | |
| 163 if (pack == NULL) | |
| 164 pack = obj; | |
| 165 else | |
| 166 { | |
| 167 lp->l_next = obj; | |
| 168 obj->l_prev = lp; | |
| 169 obj->l_next = NULL; | |
| 170 } | |
| 171 } | |
| 172 else | |
| 173 { | |
| 174 /* | |
| 175 * If we found an exact match. If it is a potion, food, or a | |
| 176 * scroll, increase the count, otherwise put it with its clones. | |
| 177 */ | |
| 178 if (exact && ISMULT(obj->o_type)) | |
| 179 { | |
| 180 op->o_count++; | |
| 181 update_mdest(obj); | |
| 182 discard(obj); | |
| 183 obj = op; | |
| 184 discarded = 1; | |
| 185 goto picked_up; | |
| 186 } | |
| 187 if ((obj->l_prev = prev(op)) != NULL) | |
| 188 obj->l_prev->l_next = obj; | |
| 189 else | |
| 190 pack = obj; | |
| 191 obj->l_next = op; | |
| 192 op->l_prev = obj; | |
| 193 } | |
| 194 picked_up: | |
| 195 /* | |
| 196 * If this was the object of something's desire, that monster will | |
| 197 * get mad and run at the hero | |
| 198 */ | |
| 199 if (!discarded) | |
| 200 update_mdest(obj); | |
| 201 | |
| 202 if (obj->o_type == AMULET) | |
| 203 amulet = TRUE; | |
| 204 /* | |
| 205 * Notify the user | |
| 206 */ | |
| 207 if (!silent) | |
| 208 { | |
| 209 if (!terse) | |
| 210 addmsg("you now have "); | |
| 211 msg("%s (%c)", inv_name(obj, !terse), pack_char(obj)); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 /* | |
| 216 * inventory: | |
| 217 * List what is in the pack | |
| 218 */ | |
| 219 inventory(list, type) | |
| 220 THING *list; | |
| 221 int type; | |
| 222 { | |
| 223 register char ch; | |
| 224 register int n_objs; | |
| 225 char inv_temp[MAXSTR]; | |
| 226 | |
| 227 n_objs = 0; | |
| 228 for (ch = 'a'; list != NULL; ch++, list = next(list)) | |
| 229 { | |
| 230 if (type && type != list->o_type && !(type == CALLABLE && | |
| 231 (list->o_type == SCROLL || list->o_type == POTION || | |
| 232 list->o_type == RING || list->o_type == STICK))) | |
| 233 continue; | |
| 234 n_objs++; | |
| 235 sprintf(inv_temp, "%c) %%s", ch); | |
| 236 add_line(inv_temp, inv_name(list, FALSE)); | |
| 237 } | |
| 238 if (n_objs == 0) | |
| 239 { | |
| 240 if (terse) | |
| 241 msg(type == 0 ? "empty handed" : | |
| 242 "nothing appropriate"); | |
| 243 else | |
| 244 msg(type == 0 ? "you are empty handed" : | |
| 245 "you don't have anything appropriate"); | |
| 246 return FALSE; | |
| 247 } | |
| 248 end_line(); | |
| 249 return TRUE; | |
| 250 } | |
| 251 | |
| 252 /* | |
| 253 * pick_up: | |
| 254 * Add something to characters pack. | |
| 255 */ | |
| 256 pick_up(ch) | |
| 257 char ch; | |
| 258 { | |
| 259 register THING *obj, *mp; | |
| 260 | |
| 261 switch (ch) | |
| 262 { | |
| 263 case GOLD: | |
| 264 if ((obj = find_obj(hero.y, hero.x)) == NULL) | |
| 265 return; | |
| 266 money(obj->o_goldval); | |
| 267 detach(lvl_obj, obj); | |
| 268 update_mdest(obj); | |
| 269 discard(obj); | |
| 270 proom->r_goldval = 0; | |
| 271 break; | |
| 272 default: | |
| 273 #ifdef WIZARD | |
| 274 debug("Where did you pick a '%s' up???", unctrol(ch)); | |
| 275 #endif | |
| 276 case ARMOR: | |
| 277 case POTION: | |
| 278 case FOOD: | |
| 279 case WEAPON: | |
| 280 case SCROLL: | |
| 281 case AMULET: | |
| 282 case RING: | |
| 283 case STICK: | |
| 284 add_pack(NULL, FALSE); | |
| 285 break; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 /* | |
| 290 * picky_inven: | |
| 291 * Allow player to inventory a single item | |
| 292 */ | |
| 293 picky_inven() | |
| 294 { | |
| 295 register THING *obj; | |
| 296 register char ch, mch; | |
| 297 | |
| 298 if (pack == NULL) | |
| 299 msg("you aren't carrying anything"); | |
| 300 else if (next(pack) == NULL) | |
| 301 msg("a) %s", inv_name(pack, FALSE)); | |
| 302 else | |
| 303 { | |
| 304 msg(terse ? "item: " : "which item do you wish to inventory: "); | |
| 305 mpos = 0; | |
| 306 if ((mch = readchar()) == ESCAPE) | |
| 307 { | |
| 308 msg(""); | |
| 309 return; | |
| 310 } | |
| 311 for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++) | |
| 312 if (ch == mch) | |
| 313 { | |
| 314 msg("%c) %s",ch,inv_name(obj, FALSE)); | |
| 315 return; | |
| 316 } | |
| 317 if (!terse) | |
| 318 msg("'%s' not in pack", unctrol(mch)); | |
| 319 msg("range is 'a' to '%c'", --ch); | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 /* | |
| 324 * get_item: | |
| 325 * Pick something out of a pack for a purpose | |
| 326 */ | |
| 327 THING * | |
| 328 get_item(purpose, type) | |
| 329 char *purpose; | |
| 330 int type; | |
| 331 { | |
| 332 register THING *obj; | |
| 333 register char ch, och; | |
| 334 | |
| 335 if (pack == NULL) | |
| 336 msg("you aren't carrying anything"); | |
| 337 else | |
| 338 { | |
| 339 for (;;) | |
| 340 { | |
| 341 if (!terse) | |
| 342 addmsg("which object do you want to "); | |
| 343 addmsg(purpose); | |
| 344 if (terse) | |
| 345 addmsg(" what"); | |
| 346 msg("? (* for list): "); | |
| 347 ch = readchar(); | |
| 348 mpos = 0; | |
| 349 /* | |
| 350 * Give the poor player a chance to abort the command | |
| 351 */ | |
| 352 if (ch == ESCAPE || ch == CTRL('G')) | |
| 353 { | |
| 354 after = FALSE; | |
| 355 msg(""); | |
| 356 return NULL; | |
| 357 } | |
| 358 if (ch == '*') | |
| 359 { | |
| 360 mpos = 0; | |
| 361 if (inventory(pack, type) == 0) | |
| 362 { | |
| 363 after = FALSE; | |
| 364 return NULL; | |
| 365 } | |
| 366 continue; | |
| 367 } | |
| 368 for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++) | |
| 369 if (ch == och) | |
| 370 break; | |
| 371 if (obj == NULL) | |
| 372 { | |
| 373 msg("please specify a letter between 'a' and '%c'", och-1); | |
| 374 continue; | |
| 375 } | |
| 376 else | |
| 377 return obj; | |
| 378 } | |
| 379 } | |
| 380 return NULL; | |
| 381 } | |
| 382 | |
| 383 /* | |
| 384 * pack_char: | |
| 385 * Return which character would address a pack object | |
| 386 */ | |
| 387 pack_char(obj) | |
