Mercurial > hg > early-roguelike
comparison urogue/pack.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Tue, 31 Jan 2017 19:56:04 -0500 |
| parents | |
| children | 74351bf23e5e |
comparison
equal
deleted
inserted
replaced
| 253:d9badb9c0179 | 256:c495a4f288c6 |
|---|---|
| 1 /* | |
| 2 pack.c - Routines to deal with the pack. | |
| 3 | |
| 4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
| 5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
| 6 All rights reserved. | |
| 7 | |
| 8 Based on "Advanced Rogue" | |
| 9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
| 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 /* | |
| 20 Notes | |
| 21 | |
| 22 The new pack is implemented through the use of bags, | |
| 23 and items are classed by their types (see rogue.h) which also | |
| 24 happen to be their display character. | |
| 25 */ | |
| 26 | |
| 27 #include <stdlib.h> | |
| 28 #include <ctype.h> | |
| 29 #include "rogue.h" | |
| 30 | |
| 31 #define ESCAPE_EXIT(x) if (x == ESCAPE) {after = FALSE; msg(""); return(NULL);} | |
| 32 #define BAD_NEWS -1 | |
| 33 #define BAD_LIST ((struct linked_list *) BAD_NEWS) | |
| 34 #define GOOD_NEWS 0 | |
| 35 | |
| 36 static char type_list[] = "!?])/=:,"; /* things to inventory */ | |
| 37 | |
| 38 /* | |
| 39 swap_top() | |
| 40 Takes an stacked object and exchanges places with the top | |
| 41 object. <node> must belong to the <top>'s stacked object list. | |
| 42 */ | |
| 43 | |
| 44 void | |
| 45 swap_top(struct linked_list *top, struct linked_list *node) | |
| 46 { | |
| 47 struct object *obt, *obn; | |
| 48 | |
| 49 obt = OBJPTR(top); | |
| 50 obn = OBJPTR(node); | |
| 51 | |
| 52 detach((obt->next_obj), node); /* Take it out of the stack */ | |
| 53 attach(lvl_obj, node); /* and put it into the level */ | |
| 54 detach(lvl_obj, top); /* Remove item from level */ | |
| 55 | |
| 56 obn->next_obj = obt->next_obj; | |
| 57 | |
| 58 if (obn->next_obj) | |
| 59 obn->next_obj->l_prev = NULL; | |
| 60 | |
| 61 attach((obn->next_obj), top); | |
| 62 } | |
| 63 | |
| 64 | |
| 65 /* | |
| 66 get_all() | |
| 67 Get as many stacked items as possible. | |
| 68 */ | |
| 69 | |
| 70 void | |
| 71 get_all(struct linked_list *top) | |
| 72 { | |
| 73 struct linked_list *node; | |
| 74 struct object *obt; | |
| 75 | |
| 76 while (top) | |
| 77 { | |
| 78 obt = OBJPTR(top); | |
| 79 node = obt->next_obj; | |
| 80 | |
| 81 rem_obj(top, FALSE); | |
| 82 | |
| 83 if (!add_pack(top, FALSE)) | |
| 84 return; | |
| 85 | |
| 86 top = node; | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 | |
| 91 /* | |
| 92 get_stack() | |
| 93 Allows the user to chose from a stack of items. | |
| 94 */ | |
| 95 | |
| 96 struct linked_list * | |
| 97 get_stack(struct linked_list *item) | |
| 98 { | |
| 99 struct object *obj; | |
| 100 char buf[2 * LINELEN]; | |
| 101 int i = 0, j; | |
| 102 struct linked_list *ll; | |
| 103 mpos = 0; | |
| 104 obj = OBJPTR(item); | |
| 105 | |
| 106 ll = obj->next_obj; | |
| 107 | |
| 108 sprintf(buf, "You are standing on top of the following items: "); | |
| 109 add_line(buf); | |
| 110 sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE)); | |
| 111 add_line(buf); | |
| 112 | |
| 113 while (ll) | |
| 114 { | |
| 115 i++; | |
| 116 obj = OBJPTR(ll); | |
| 117 sprintf(buf, "%d) -- %s", i, inv_name(obj, TRUE)); | |
| 118 add_line(buf); | |
| 119 ll = next(ll); | |
| 120 } | |
| 121 | |
| 122 end_line(); | |
| 123 | |
| 124 msg("Which one do you want to pick up? [* for all] "); | |
| 125 | |
| 126 switch(get_string(buf, cw)) | |
| 127 { | |
| 128 case NORM: | |
| 129 break; | |
| 130 case QUIT: /* pick up nothing */ | |
| 131 msg(""); | |
| 132 return (NULL); | |
| 133 } | |
| 134 | |
| 135 if (buf[0] == '*') | |
| 136 { | |
| 137 get_all(item); | |
| 138 msg(""); | |
| 139 return(NULL); | |
| 140 } | |
| 141 else | |
| 142 { | |
| 143 i = atoi(buf); | |
| 144 | |
| 145 if (i) | |
| 146 { | |
| 147 obj = OBJPTR(item); | |
| 148 ll = obj->next_obj; | |
| 149 j = 1; | |
| 150 | |
| 151 while (ll && (j != i)) | |
| 152 { | |
| 153 ll = next(ll); | |
| 154 j++; | |
| 155 } | |
| 156 | |
| 157 if (ll) | |
| 158 { | |
| 159 swap_top(item, ll); | |
| 160 return(ll); | |
| 161 } | |
| 162 else | |
| 163 { | |
| 164 debug("Got past last item while picking up."); | |
| 165 return(item); | |
| 166 } | |
| 167 } | |
| 168 else | |
| 169 return (item); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 /* | |
| 174 add_pack() | |
| 175 Pick up an object and add it to the pack. If the argument is | |
| 176 non-null use it as the linked_list pointer instead of getting it off the | |
| 177 ground. | |
| 178 */ | |
| 179 | |
| 180 int | |
| 181 add_pack(struct linked_list *item, int print_message) | |
| 182 { | |
| 183 struct object *obj, *op; | |
| 184 int from_floor; | |
| 185 | |
| 186 if (item == NULL) | |
| 187 { | |
| 188 from_floor = TRUE; | |
| 189 | |
| 190 if ((item = find_obj(hero.y, hero.x)) == NULL) | |
| 191 { | |
| 192 msg("Nothing to pick up."); | |
| 193 return(FALSE); | |
| 194 } | |
| 195 } | |
| 196 else | |
| 197 from_floor = FALSE; | |
| 198 | |
| 199 if (from_floor) | |
| 200 { | |
| 201 item = get_stack(item); | |
| 202 | |
| 203 if (!item) | |
| 204 return(FALSE); | |
| 205 } | |
| 206 | |
| 207 obj = OBJPTR(item); | |
| 208 | |
| 209 /* If it is gold, just add its value to rogue's purse and get rid of */ | |
| 210 | |
| 211 if (obj->o_type == GOLD) | |
| 212 { | |
| 213 struct linked_list *mitem; | |
| 214 struct thing *tp; | |
| 215 | |
| 216 if (print_message) | |
| 217 { | |
| 218 if (!terse) | |
| 219 addmsg("You found "); | |
| 220 | |
| 221 msg("%d gold pieces.", obj->o_count); | |
| 222 } | |
| 223 | |
| 224 /* | |
| 225 * First make sure no greedy monster is after this gold. If | |
| 226 * so, make the monster run after the rogue instead. | |
| 227 */ | |
| 228 | |
| 229 for (mitem = mlist; mitem != NULL; mitem = next(mitem)) | |
| 230 { | |
| 231 tp = THINGPTR(mitem); | |
| 232 | |
| 233 if (tp->t_horde==obj) | |
| 234 { | |
| 235 tp->t_ischasing = TRUE; | |
| 236 tp->t_chasee = &player; | |
| 237 tp->t_horde = NULL; | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 /* | |
| 242 * This will cause problems if people are able to drop and | |
| 243 * pick up gold, or when GOLDSTEAL monsters are killed. | |
| 244 */ | |
| 245 | |
| 246 /* Thieves get EXP for gold they pick up */ | |
| 247 | |
| 248 if (player.t_ctype == C_THIEF) | |
| 249 { | |
| 250 pstats.s_exp += obj->o_count / 4; | |
| 251 check_level(); | |
| 252 } | |
| 253 | |
| 254 purse += obj->o_count; | |
| 255 | |
| 256 if (from_floor) | |
| 257 rem_obj(item, TRUE); /* Remove object from the level */ | |
| 258 | |
| 259 return (TRUE); | |
| 260 } | |
| 261 | |
| 262 /* see if he can carry any more weight */ | |
| 263 | |
| 264 if (itemweight(obj) + pstats.s_pack > pstats.s_carry) | |
| 265 { | |
| 266 msg("Too much for you to carry."); | |
| 267 | |
| 268 if (print_message) | |
| 269 { | |
| 270 msg("%s onto %s", terse ? "Moved" : "You moved", | |
| 271 inv_name(obj, LOWERCASE)); | |
| 272 } | |
| 273 | |
| 274 return(FALSE); | |
| 275 } | |
| 276 | |
| 277 /* | |
| 278 * Link it into the pack. If the item can be grouped, try to find its | |
| 279 * neighbors and bump the count. A special case is food, which can't | |
| 280 * be grouped, but an exact match allows the count to get | |
| 281 * incremented. | |
| 282 */ | |
| 283 | |
| 284 if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL) | |
| 285 { | |
| 286 op->o_count += obj->o_count; /* add it to the rest */ | |
| 287 | |
| 288 if (from_floor) | |
| 289 rem_obj(item, FALSE); | |
| 290 | |
| 291 pack_report(op, print_message, "You now have "); | |
| 292 | |
| 293 return(TRUE); | |
| 294 } | |
| 295 | |
| 296 /* Check for and deal with scare monster scrolls */ | |
| 297 | |
| 298 if (obj->o_type == SCROLL && obj->o_which == S_SCARE) | |
| 299 if (obj->o_flags & ISCURSED) | |
| 300 { | |
| 301 msg("The scroll turns to dust as you pick it up."); | |
| 302 rem_obj(item, TRUE); | |
| 303 return(TRUE); | |
| 304 } | |
| 305 | |
| 306 /* Check if there is room */ | |
| 307 | |
| 308 if (count_bag(pack, obj->o_type, NULL) == max_print()) | |
| 309 { | |
| 310 msg("You have no room for more %s.", name_type(obj->o_type)); | |
| 311 | |
| 312 if (print_message) | |
| 313 { | |
| 314 obj = OBJPTR(item); | |
| 315 msg("%s onto %s.", terse ? "Moved" : "You moved", | |
| 316 inv_name(obj, LOWERCASE)); | |
| 317 } | |
| 318 | |
| 319 return(FALSE); | |
| 320 } | |
| 321 | |
| 322 /* | |
| 323 * finally, add the new item to the bag, and free up the linked list | |
| 324 * on top of it. | |
| 325 */ | |
| 326 | |
| 327 if (from_floor) | |
| 328 rem_obj(item, FALSE); | |
| 329 | |
| 330 push_bag(&pack, obj); | |
| 331 pack_report(obj, print_message, "You now have "); | |
| 332 ur_free(item); | |
| 333 | |
| 334 return(TRUE); /* signal success */ | |
| 335 } | |
| 336 | |
| 337 /* | |
| 338 pack_report() | |
| 339 Notify the user about the results of the pack operation and do some | |
| 340 post processing. | |
| 341 */ | |
| 342 | |
| 343 void | |
| 344 pack_report(object *obj, int print_message, char *message) | |
| 345 { | |
| 346 /* Notify the user */ | |
| 347 | |
| 348 if (print_message) | |
| 349 { | |
| 350 if (!terse) | |
| 351 addmsg(message); | |
| 352 | |
| 353 msg("(%c%c) %s.", obj->o_type, print_letters[get_ident(obj)], | |
| 354 inv_name(obj, !terse)); | |
| 355 } | |
| 356 | |
| 357 if (obj->o_type == ARTIFACT) | |
| 358 { | |
| 359 has_artifact |= (1 << obj->o_which); | |
| 360 picked_artifact |= (1 << obj->o_which); | |
| 361 | |
| 362 if (!(obj->ar_flags & ISUSED)) | |
| 363 { | |
| 364 obj->ar_flags |= ISUSED; | |
| 365 pstats.s_exp += arts[obj->o_which].ar_worth / 10; | |
| 366 check_level(); | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 updpack(); | |
| 371 | |
| 372 return; | |
| 373 } | |
| 374 | |
| 375 /* | |
| 376 inventory() | |
| 377 list what is in the pack | |
| 378 */ | |
| 379 | |
| 380 void | |
| 381 inventory(struct linked_list *container, int type) | |
| 382 { | |
| 383 int cnt; | |
