/* * Allow one item to "absorb" another, assuming they are similar */ void object_absorb(object_type *o_ptr, object_type *j_ptr) { s32b total = o_ptr->number + j_ptr->number; /* Add together the item counts */ o_ptr->number = ((total < MAX_STACK_SIZE) ? total : (MAX_STACK_SIZE - 1)); /* Probably move most or indeed all of this to ToME code instead of T-engine code */ /* Hack -- blend "known" status */ if (object_known_p(j_ptr)) object_known(o_ptr); /* Hack -- clear "storebought" if only one has it */ if (((o_ptr->ident & IDENT_STOREB) || (j_ptr->ident & IDENT_STOREB)) && (!((o_ptr->ident & IDENT_STOREB) && (j_ptr->ident & IDENT_STOREB)))) { if (j_ptr->ident & IDENT_STOREB) j_ptr->ident &= 0xEF; if (o_ptr->ident & IDENT_STOREB) o_ptr->ident &= 0xEF; } /* Hack -- blend "mental" status */ if (j_ptr->ident & (IDENT_MENTAL)) o_ptr->ident |= (IDENT_MENTAL); /* Hack -- blend "inscriptions" */ if (j_ptr->note) o_ptr->note = j_ptr->note; /* Hack -- could average discounts XXX XXX XXX */ /* Hack -- save largest discount XXX XXX XXX */ if (o_ptr->discount < j_ptr->discount) o_ptr->discount = j_ptr->discount; process_hooks(HOOK_OBJECT_ABSORB,"(O,O)",o_ptr,j_ptr); }
static void _upgrade_weapon(int tval, int sval) { object_type *o_ptr = _weapon(); object_prep(o_ptr, lookup_kind(tval, sval)); o_ptr->to_h = p_ptr->lev / 5; o_ptr->to_d = p_ptr->lev / 3; add_flag(o_ptr->art_flags, TR_NO_REMOVE); object_aware(o_ptr); object_known(o_ptr); o_ptr->ident |= IDENT_MENTAL; p_ptr->update |= PU_BONUS; p_ptr->window |= PW_INVEN | PW_EQUIP | PW_PLAYER; }
/* * Describe fake object */ static void desc_obj_fake(int k_idx) { object_kind *k_ptr = &k_info[k_idx]; object_type object_type_body; object_type *o_ptr = &object_type_body; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; /* Check for known artifacts, display them as artifacts */ if (kf_has(k_ptr->flags_kind, KF_INSTA_ART) && artifact_is_known(get_artifact_from_kind(k_ptr))) { desc_art_fake(get_artifact_from_kind(k_ptr)); return; } /* Update the object recall window */ track_object_kind(k_idx); handle_stuff(p_ptr); /* Wipe the object */ object_wipe(o_ptr); /* Create the artifact */ object_prep(o_ptr, k_idx, EXTREMIFY); /* Hack -- its in the store */ if (k_info[k_idx].aware) o_ptr->ident |= (IDENT_STORE); /* It's fully know */ if (!k_info[k_idx].flavor) object_known(o_ptr); /* Hack -- Handle stuff */ handle_stuff(p_ptr); /* Describe */ tb = object_info(o_ptr, OINFO_DUMMY); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL | ODESC_CAPITAL); textui_textblock_show(tb, area, format("%s", header)); textblock_free(tb); }
bool quest_poison_quest_hook(char *fmt) { object_type forge, *q_ptr; s32b q_idx; q_idx = get_next_arg(fmt); if (q_idx != QUEST_POISON) return FALSE; q_ptr = &forge; object_prep(q_ptr, lookup_kind(TV_POTION2, SV_POTION2_CURE_WATER)); q_ptr->number = 99; object_aware(q_ptr); object_known(q_ptr); q_ptr->ident |= IDENT_STOREB; q_ptr->note = quark_add("quest"); (void)inven_carry(q_ptr, FALSE); del_hook(HOOK_INIT_QUEST, quest_poison_quest_hook); process_hooks_restart = TRUE; return FALSE; }
/* * Scatter some "great" objects near the player */ void acquirement(s32b y1, s32b x1, s32b num, bool great, bool known) { object_type *i_ptr; /* Acquirement */ while (num--) { /* Get local object */ i_ptr = make_object(TRUE, great, NULL); /* Make a good (or great) object (if possible) */ if (i_ptr == NULL) return; if (known) { object_aware(i_ptr); object_known(i_ptr); } /* Drop the object */ drop_near(i_ptr, -1, y1, x1); } }
/** * Search for hidden things */ bool search(bool verbose) { int py = p_ptr->py; int px = p_ptr->px; int y, x, chance; bool found = FALSE; object_type *o_ptr; /* Start with base search ability */ chance = p_ptr->state.skills[SKILL_SEARCH]; /* Penalize various conditions */ if (p_ptr->timed[TMD_BLIND] || no_light()) chance = chance / 10; if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) chance = chance / 10; /* Prevent fruitless searches */ if (chance <= 0) { if (verbose) { msg_print("You can't make out your surroundings well enough to search."); /* Cancel repeat */ disturb(0, 0); } return FALSE; } /* Search the nearby grids, which are always in bounds */ for (y = (py - 1); y <= (py + 1); y++) { for (x = (px - 1); x <= (px + 1); x++) { feature_type *f_ptr = &f_info[cave_feat[y][x]]; /* Sometimes, notice things */ if (randint0(100) < chance) { /* Invisible trap */ if (tf_has(f_ptr->flags, TF_TRAP_INVIS)) { found = TRUE; /* Pick a trap */ pick_trap(y, x); /* Message */ msg_print("You have found a trap."); /* Disturb */ disturb(0, 0); } /* Secret door */ if (cave_feat[y][x] == FEAT_SECRET) { found = TRUE; /* Message */ msg_print("You have found a secret door."); /* Pick a door */ place_closed_door(y, x); /* Disturb */ disturb(0, 0); } /* Scan all objects in the grid */ for (o_ptr = get_first_object(y, x); o_ptr; o_ptr = get_next_object(o_ptr)) { /* Skip non-chests */ if (o_ptr->tval != TV_CHEST) continue; /* Skip disarmed chests */ if (o_ptr->pval <= 0) continue; /* Skip non-trapped chests */ if (!chest_traps[o_ptr->pval]) continue; /* Identify once */ if (!object_known_p(o_ptr)) { found = TRUE; /* Message */ msg_print("You have discovered a trap on the chest!"); /* Know the trap */ object_known(o_ptr); /* Notice it */ disturb(0, 0); } } } } } if (verbose && !found) { if (chance >= 100) msg_print("There are no secrets here."); else msg_print("You found nothing."); } return TRUE; }
/* * Dump the object information a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_a_info_txt(void) { int i, j, bc; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; artifact_type *a_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "a_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: a_info.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 0; i < z_info->art_norm_max; i++) { int counter = 1; char o_name[80]; object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Get the object */ a_ptr = &a_info[i]; /* Ignore unused objects */ if (!strlen(a_ptr->name)) { fprintf(fff, "## empty space (available for artifact) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%s\n", i, a_ptr->name); /* Write the complete name of the artifact*/ make_fake_artifact(i_ptr, i); /*identify it*/ /* Identify it */ object_aware(i_ptr); object_known(i_ptr); i_ptr->ident |= (IDENT_MENTAL); /* Get a description to dump */ object_desc(o_name, sizeof(o_name), i_ptr, TRUE, 0); /*dump the long name*/ fprintf(fff, "desc:%d: # %s\n", i, o_name); /* Write I: line */ fprintf(fff, "I:%d:%d:%d:%d\n", i, a_ptr->tval, a_ptr->sval, a_ptr->pval); /* Write W: line */ fprintf(fff, "W:%d:%d:%d:%d:%d\n", i, a_ptr->a_level, a_ptr->a_rarity, a_ptr->weight, a_ptr->cost); /* Write P: line */ fprintf(fff, "P:%d:%d:%d:d:%d:%d:%d:%d\n", i, a_ptr->ac, a_ptr->dd, a_ptr->ds, a_ptr->to_h, a_ptr->to_d, a_ptr->to_a); /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, a_ptr->a_flags1, 1, i); dump_flags(fff, a_ptr->a_flags2, 2, i); dump_flags(fff, a_ptr->a_flags3, 3, i); dump_flags(fff, a_ptr->a_native, 4, i); /* Write the A line */ fprintf(fff, "A:%d:%d:%d:%d\n", i, a_ptr->activation, a_ptr->time, a_ptr->randtime); /* Acquire the description */ desc = a_text + a_ptr->text; dlen = strlen(desc); if (dlen < 1) { /* Space between entries */ fprintf(fff, "\n\n\n"); continue; } /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all objects have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 12; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
/*used to check the power of artifacts. Currently unused*/ void dump_artifact_power(void) { int i; char buf[1024]; int fd; FILE *fff = NULL; artifact_type *a_ptr; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "power.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: artifact_power.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 1; i < z_info->art_norm_max; i++) { s32b power; char o_name[80]; object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Get the object */ a_ptr = &a_info[i]; /* Ignore unused objects */ if (!strlen(a_ptr->name)) { fprintf(fff, "## empty space (available for artifact) ##\n\n"); continue; } /* Write the complete name of the artifact*/ make_fake_artifact(i_ptr, i); /* Identify it */ object_aware(i_ptr); object_known(i_ptr); i_ptr->ident |= (IDENT_MENTAL); /* Get a description to dump */ object_desc(o_name, sizeof(o_name), i_ptr, TRUE, 0); power = artifact_power(i); /*dump the information*/ fprintf(fff, "%9d is the power of %55s, tval is %6d \n", power, o_name, a_ptr->tval); } /* Done */ fclose(fff); }
/** * Handle player hitting a real trap. Rewritten in Oangband to allow a * greater variety of traps, with effects controlled by dungeon level. * To allow a trap to choose one of a variety of effects consistantly, * the quick RNG is often used, and xy coordinates input as a seed value. */ extern void hit_trap(int y, int x) { int i, j, k, num; int dam = 0; int nastyness, selection; feature_type *f_ptr = &f_info[cave_feat[y][x]]; cptr name = f_ptr->name; /* Use the "simple" RNG to insure that traps are consistant. */ Rand_quick = TRUE; /* Use the coordinates of the trap to seed the RNG. */ Rand_value = y * x; /* Disturb the player */ disturb(0, 0); /* Analyze XXX XXX XXX */ switch (cave_feat[y][x]) { /* trap door. */ case FEAT_TRAP_HEAD + 0x00: { Rand_quick = FALSE; /* Paranoia -NRM- */ if (((stage_map[p_ptr->stage][STAGE_TYPE] == CAVE) || (stage_map[p_ptr->stage][STAGE_TYPE] == VALLEY)) && (!stage_map[p_ptr->stage][DOWN])) { cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); msg_print("The trap fails!"); break; } msg_print("You fall through a trap door!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently down to the next level."); } else { dam = damroll(2, 8); take_hit(dam, name); } /* Remember where we came from */ p_ptr->last_stage = p_ptr->stage; if (!stage_map[p_ptr->stage][DOWN]) { /* Set the ways forward and back */ stage_map[255][UP] = p_ptr->stage; stage_map[p_ptr->stage][DOWN] = 255; stage_map[255][DEPTH] = p_ptr->depth + 1; } /* New stage */ p_ptr->stage = stage_map[p_ptr->stage][DOWN]; /* New depth */ p_ptr->depth = stage_map[p_ptr->stage][DEPTH]; /* Leaving */ p_ptr->leaving = TRUE; Rand_quick = TRUE; break; } /* pits. */ case FEAT_TRAP_HEAD + 0x01: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(20) == 1) nastyness += 20; else if (randint1(5) == 1) nastyness += 10; /* Player is now in pit. */ monster_swap(p_ptr->py, p_ptr->px, y, x); /* Center on player. */ y = p_ptr->py; x = p_ptr->px; /* pit of daggers. */ if ((nastyness > 80) && (randint1(3) != 3)) { msg_print("You fall into a pit of daggers!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid setting off the daggers."); } else { /* a trap of morgul. */ if (randint1(6) == 1) { Rand_quick = FALSE; msg_print ("A single coldly gleaming dagger pierces you deeply!"); msg_print ("You feel a deadly chill slowly withering your soul."); /* activate the Black Breath. */ p_ptr->black_breath = TRUE; /* lots of damage. */ dam = damroll(20, 15); /* undead may be attracted. */ if (randint1(2) == 1) { msg_print ("Undead suddenly appear and call you to them!"); k = randint1(3) + 2; for (i = 0; i < k; i++) { summon_specific(y, x, FALSE, p_ptr->depth, SUMMON_UNDEAD); } } /* morgul-traps are one-time only. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); Rand_quick = TRUE; } else { Rand_quick = FALSE; /* activate the ordinary daggers. */ msg_print("Daggers pierce you everywhere!"); k = randint1(10) + 5; for (i = 0; i < k; i++) { dam += damroll(3, 4); } Rand_quick = TRUE; } /* cut the player. */ (void) inc_timed(TMD_CUT, randint1(dam), TRUE); /* Take the damage. */ take_hit(dam, name); } } /* poisoned spiked pit. */ else if ((nastyness > 55) && (randint1(3) != 3)) { msg_print("You fall into a spiked pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid touching the spikes."); } else { Rand_quick = FALSE; /* Base damage */ dam = damroll(2, 6); /* Extra spike damage */ if (randint0(100) < 85) { bool was_poisoned; msg_print("You are impaled on poisonous spikes!"); dam = dam * (randint1(6) + 3); (void) inc_timed(TMD_CUT, randint1(dam), TRUE); was_poisoned = pois_hit(dam); if (!was_poisoned) msg_print("The poison does not affect you!"); } /* Take the damage */ take_hit(dam, name); Rand_quick = TRUE; } } /* spiked pit. */ else if ((nastyness > 30) && (randint1(3) != 3)) { msg_print("You fall into a spiked pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid touching the spikes."); } else { Rand_quick = FALSE; /* Base damage */ dam = damroll(2, 6); /* Extra spike damage */ if (randint0(100) < 85) { msg_print("You are impaled!"); dam = dam * (2 + randint1(4)); (void) inc_timed(TMD_CUT, randint1(dam), TRUE); } /* Take the damage */ take_hit(dam, name); Rand_quick = TRUE; } } /* ordinary pit in all other cases. */ else { msg_print("You fall into a pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the bottom of the pit."); } else { Rand_quick = FALSE; dam = damroll(2, 6); take_hit(dam, name); Rand_quick = TRUE; } } break; } /* stat-reducing dart traps. */ case FEAT_TRAP_HEAD + 0x02: { /* decide if the dart hits. */ if (check_trap_hit(50 + p_ptr->depth)) { /* select a stat to drain. */ selection = randint0(6); Rand_quick = FALSE; msg_print("A small dart hits you!"); dam = damroll(1, 4); take_hit(dam, name); /* Determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); /* decide how much to drain the stat by. */ if ((nastyness > 50) && (randint1(3) == 1)) { num = randint1(4); } else num = 1; /* drain the stat. */ for (i = 0; i < num; i++) { (void) do_dec_stat(selection); } Rand_quick = TRUE; } else { msg_print("A small dart barely misses you."); } break; } /* discolored spots. */ case FEAT_TRAP_HEAD + 0x03: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(5) == 1) nastyness += 10; /* pick a elemental attack type. */ selection = randint1(4); /* electicity trap. */ if (selection == 1) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are struck by lightning!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You get zapped!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; elec_dam(dam, "an electricity trap"); Rand_quick = TRUE; } /* frost trap. */ if (selection == 2) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are lost within a blizzard!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are coated in frost!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; cold_dam(dam, "a frost trap"); Rand_quick = TRUE; } /* fire trap. */ if (selection == 3) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are enveloped in a column of fire!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are surrounded by flames!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; fire_dam(dam, "a fire trap"); Rand_quick = TRUE; } /* acid trap. */ if (selection == 4) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("A cauldron of acid is tipped over your head!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are splashed with acid!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; acid_dam(dam, "an acid trap"); Rand_quick = TRUE; } break; } /* gas traps. */ case FEAT_TRAP_HEAD + 0x04: { selection = randint1(4); /* blinding trap. */ if (selection == 1) { msg_print("You are surrounded by a black gas!"); if (!p_ptr->state.no_blind) { Rand_quick = FALSE; (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE); Rand_quick = TRUE; } } else notice_obj(OF_SEEING, 0); /* confusing trap. */ if (selection == 2) { msg_print ("You are surrounded by a gas of scintillating colors!"); if (!p_resist_good(P_RES_CONFU)) { Rand_quick = FALSE; (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); Rand_quick = TRUE; } else notice_other(IF_RES_CONFU, 0); } /* poisoning trap. */ if (selection == 3) { msg_print("You are surrounded by a pungent green gas!"); Rand_quick = FALSE; pois_hit(25); Rand_quick = TRUE; } /* sleeping trap. */ if (selection == 4) { msg_print("You are surrounded by a strange white mist!"); if (!p_ptr->state.free_act) { (void) inc_timed(TMD_PARALYZED, randint0(10) + 5, TRUE); } else notice_obj(OF_FREE_ACT, 0); } break; } /* summoning traps. */ case FEAT_TRAP_HEAD + 0x05: { sound(MSG_SUM_MONSTER); /* sometimes summon thieves. */ if ((p_ptr->depth > 8) && (randint1(5) == 1)) { msg_print("You have aroused a den of thieves!"); Rand_quick = FALSE; num = 2 + randint1(3); for (i = 0; i < num; i++) { (void) summon_specific(y, x, FALSE, p_ptr->depth, SUMMON_THIEF); } Rand_quick = TRUE; } /* sometimes summon a nasty unique. */ else if (randint1(8) == 1) { msg_print("You are enveloped in a cloud of smoke!"); Rand_quick = FALSE; (void) summon_specific(y, x, FALSE, p_ptr->depth + 5, SUMMON_UNIQUE); Rand_quick = TRUE; } /* otherwise, the ordinary summon monsters. */ else { msg_print("You are enveloped in a cloud of smoke!"); Rand_quick = FALSE; num = 2 + randint1(3); for (i = 0; i < num; i++) { (void) summon_specific(y, x, FALSE, p_ptr->depth, 0); } Rand_quick = TRUE; } /* these are all one-time traps. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); break; } /* dungeon alteration traps. */ case FEAT_TRAP_HEAD + 0x06: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(5) == 1) nastyness += 10; /* make room for alterations. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); /* Everything truely random from here on. */ Rand_quick = FALSE; /* dungeon destruction trap. */ if ((nastyness > 60) && (randint1(12) == 1)) { msg_print ("A ear-splitting howl shatters your mind as the dungeon is smashed by hammer blows!"); (void) destroy_level(FALSE); /* the player is hard-hit. */ (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE); (void) inc_timed(TMD_STUN, randint1(50) + 50, TRUE); dam = damroll(15, 15); take_hit(dam, name); } /* earthquake trap. */ else if ((nastyness > 20) && (randint1(4) == 1)) { msg_print("A tremor shakes the earth around you"); earthquake(y, x, 10, FALSE); } /* falling rock trap. */ else if ((nastyness > 4) && (randint1(2) == 1)) { msg_print("A rock falls on your head."); dam = damroll(2, 10); take_hit(dam, name); (void) inc_timed(TMD_STUN, randint1(10) + 10, TRUE); } /* a few pebbles. */ else { msg_print("A bunch of pebbles rain down on you."); dam = damroll(1, 8); take_hit(dam, name); } Rand_quick = TRUE; break; } /* various char and equipment-alteration traps, lumped together to * avoid any one effect being too common (some of them can be rather * nasty). */ case FEAT_TRAP_HEAD + 0x07: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint0(100); /* these are all one-time traps. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); /* Everything truely random from here on. */ Rand_quick = FALSE; /* trap of drain wands. */ if (nastyness < 15) { /* Hold the object information. */ object_type *o_ptr; /* Find an item */ for (i = 0; i < 20; i++) { /* Pick an item */ i = randint0(INVEN_PACK - p_ptr->pack_size_reduce); /* Obtain the item */ o_ptr = &p_ptr->inventory[i]; /* use "num" to decide if a item can be uncharged. By * default, assume it can't. */ num = 0; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Drain charged wands/staffs/rods */ if ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_ROD)) { /* case of charged wands/staffs. */ if (((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)) && (o_ptr->pval)) num = 1; /* case of charged rods. */ if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout < randcalc(o_ptr->time, 0, MINIMISE))) num = 1; if (num == 1) { /* Message */ msg_print("Energy drains from your pack!"); /* Uncharge */ if ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)) o_ptr->pval = 0; if (o_ptr->tval == TV_ROD) o_ptr->timeout = randcalc(o_ptr->time, 0, RANDOMISE) * o_ptr->number * 2; /* Combine / Reorder the pack */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); /* not more than one inventory slot effected. */ break; } else continue; } } } /* trap of forgetting. */ else if (nastyness < 35) { if (check_save(100)) { msg_print("You hang on to your memories!"); } else if (lose_all_info()) { msg_print("Your memories fade away."); } } /* trap of alter reality. */ else if (nastyness < 50) { if (OPT(adult_ironman)) msg_print("Nothing happens."); else { msg_print("The world changes!"); /* Leaving */ p_ptr->leaving = TRUE; } } /* trap of remold player. */ else if (nastyness < 75) { int max1, cur1, max2, cur2, ii, jj; msg_print("You feel yourself being twisted by wild magic!"); if (check_save(100)) { msg_print("You resist the effects!"); } else { msg_print("Your body starts to scramble..."); /* Pick a pair of stats */ ii = randint0(6); for (jj = ii; jj == ii; jj = randint0(6)) /* loop */ ; max1 = p_ptr->stat_max[ii]; cur1 = p_ptr->stat_cur[ii]; max2 = p_ptr->stat_max[jj]; cur2 = p_ptr->stat_cur[jj]; p_ptr->stat_max[ii] = max2; p_ptr->stat_cur[ii] = cur2; p_ptr->stat_max[jj] = max1; p_ptr->stat_cur[jj] = cur1; p_ptr->update |= (PU_BONUS); } } /* time ball trap. */ else if (nastyness < 90) { msg_print("You feel time itself assault you!"); /* Target the player with a radius 0 ball attack. */ fire_meteor(0, GF_TIME, p_ptr->py, p_ptr->px, 75, 0, TRUE); } /* trap of bugs gone berserk. */ else { /* explain what the dickens is going on. */ msg_print("GRUESOME Gnawing Bugs leap out at you!"); if (!p_resist_good(P_RES_CONFU)) { (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); } else notice_other(IF_RES_CONFU, 0); if (!p_resist_good(P_RES_CHAOS)) { (void) inc_timed(TMD_IMAGE, randint1(40), TRUE); } else notice_other(IF_RES_CHAOS, 0); /* XXX (hard coded) summon 3-6 bugs. */ k = randint1(4) + 2; for (i = 0; i < k; ++i) { /* Look for a location */ for (j = 0; j < 20; ++j) { /* Pick a (scattered) distance. */ int d = (j / 10) + randint1(3); /* Pick a location */ scatter(&y, &x, y, x, d, 0); /* Require passable terrain */ if (!cave_passable_bold(y, x)) continue; /* Hack -- no summon on glyph of warding */ if (cave_feat[y][x] == FEAT_RUNE_PROTECT) continue; /* Okay */ break; } /* Attempt to place the awake bug */ place_monster_aux(y, x, 453, FALSE, TRUE); } /* herald the arrival of bugs. */ msg_print("AAAAAAAHHHH! THEY'RE EVERYWHERE!"); } Rand_quick = TRUE; break; } /* teleport trap */ case FEAT_TRAP_HEAD + 0x08: { if (stage_map[p_ptr->stage][STAGE_TYPE] >= CAVE) msg_print("You teleport across the dungeon."); else msg_print("You teleport across the wilderness."); Rand_quick = FALSE; teleport_player(250, FALSE); Rand_quick = TRUE; break; } /* murder holes. */ case FEAT_TRAP_HEAD + 0x09: { /* hold the object info. */ object_type *o_ptr; object_type object_type_body; /* hold the missile type and name. */ int sval = 0; int tval = 0; cptr missile_name = ""; /* Determine the missile type and base damage. */ if (randint1(3) == 1) { if (p_ptr->depth < 40) { missile_name = "shot"; dam = damroll(2, 3); tval = TV_SHOT; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker shot"; dam = damroll(3, 7); tval = TV_SHOT; sval = SV_AMMO_HEAVY; } } else if (randint1(2) == 1) { if (p_ptr->depth < 55) { missile_name = "arrow"; dam = damroll(2, 4); tval = TV_ARROW; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker arrow"; dam = damroll(3, 9); tval = TV_ARROW; sval = SV_AMMO_HEAVY; } } else { if (p_ptr->depth < 65) { missile_name = "bolt"; dam = damroll(2, 5); tval = TV_BOLT; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker bolt"; dam = damroll(3, 11); tval = TV_BOLT; sval = SV_AMMO_HEAVY; } } /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { msg_format("A %s hits you from above.", missile_name); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was well-aimed!"); dam *= 1 + randint1(2); } if (randint1(2) == 1) { msg_print("It gouges you!"); dam = 3 * dam / 2; /* cut the player. */ (void) inc_timed(TMD_CUT, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_format("A %s wizzes by your head.", missile_name); /* these will eventually run out of ammo. */ Rand_quick = FALSE; if (randint0(8) == 0) { cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); } Rand_quick = TRUE; /* Get local object */ o_ptr = &object_type_body; /* Make a missile, identify it, and drop it near the player. */ object_prep(o_ptr, lookup_kind(tval, sval), MINIMISE); object_aware(o_ptr); object_known(o_ptr); drop_near(o_ptr, -1, y, x, TRUE); break; } /* falling tree branch */ case FEAT_TRAP_HEAD + 0x0A: { /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { /* Take damage */ dam = damroll(3, 5); msg_print("A branch hits you from above."); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was heavy!"); dam = 3 * dam / 2; /* stun the player. */ (void) inc_timed(TMD_STUN, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_print("A falling branch just misses you."); /* No more */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_TREE); break; } /* falling tree branch */ case FEAT_TRAP_HEAD + 0x0B: { /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { /* Take damage */ dam = damroll(3, 5); msg_print("A branch hits you from above."); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was heavy!"); dam = 3 * dam / 2; /* stun the player. */ (void) inc_timed(TMD_STUN, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_print("A falling branch just misses you."); /* No more */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_TREE2); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0C: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0D: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0E: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0F: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } } /* Revert to usage of the complex RNG. */ Rand_quick = FALSE; }
/* * Allocate objects upon opening a chest. * * Disperse treasures from the given chest, centered at (x,y). * * In Oangband, chests are nice finds. Small chests distribute 3-5 items, * while large chests can distribute 5-7. Item types are biased to be * useful for the character, and they can frequently be of good quality * (or better). Code in object2.c helps these items be even better. -LM- * * The "value" of the items in a chest is based on the "power" of the chest, * which is in turn based on the level on which the chest is generated. */ static void chest_death(bool scatter, int y, int x, s16b o_idx) { int number, i; bool obj_success=FALSE; object_type *o_ptr; object_type *i_ptr; object_type object_type_body; /* Access chest */ o_ptr = &o_list[o_idx]; /* Determine how much to drop. */ if (o_ptr->sval >= SV_CHEST_MIN_LARGE) number = 4 + randint1(3); else number = 2 + randint1(3); /* Zero pval means empty chest */ if (!o_ptr->pval) number = 0; /* Opening a chest */ opening_chest = TRUE; /* Determine the "value" of the items */ object_level = ABS(o_ptr->pval); /* Select an item type that the chest will disperse. */ required_tval = get_choice(); /* Drop some objects (non-chests) */ for (; number > 0; --number) { /* Get local object */ i_ptr = &object_type_body; /* Wipe the object */ object_wipe(i_ptr); /* Make an object with a specified tval. Grant a possibility for * items to be forced good, or even great. With the new definitions * of goodness, this can make for quite interesting loot. -LM- */ switch (required_tval) { case TV_HARD_ARMOR: case TV_SOFT_ARMOR: case TV_DRAG_ARMOR: case TV_SHIELD: case TV_CLOAK: case TV_BOOTS: case TV_GLOVES: case TV_HELM: case TV_CROWN: case TV_BOW: case TV_SWORD: case TV_HAFTED: case TV_POLEARM: case TV_DIGGING: case TV_SHOT: case TV_BOLT: case TV_ARROW: { if (randint1(200) < object_level) { obj_success=make_object(i_ptr, TRUE, TRUE, TRUE); break; } else if (randint1(40) < object_level) { obj_success=make_object(i_ptr, TRUE, FALSE, TRUE); break; } else { obj_success=make_object(i_ptr, FALSE, FALSE, TRUE); break; } } case TV_MAGIC_BOOK: case TV_PRAYER_BOOK: case TV_DRUID_BOOK: case TV_NECRO_BOOK: { if (randint1(80) < object_level) { obj_success=make_object(i_ptr, TRUE, FALSE, TRUE); } else { obj_success=make_object(i_ptr, FALSE, FALSE, TRUE); } break; } case TV_SCROLL: case TV_POTION: case TV_RING: case TV_AMULET: case TV_WAND: case TV_STAFF: case TV_ROD: { if (randint1(100) < (object_level - 10) / 2) { obj_success=make_object(i_ptr, TRUE, FALSE, TRUE); } else { obj_success=make_object(i_ptr, FALSE, FALSE, TRUE); } break; } default: { obj_success=make_object(i_ptr, FALSE, FALSE, TRUE); break; } } /* If no object was made, we need to try another tval. */ if (!obj_success) { required_tval = get_choice(); } /* If chest scatters its contents, pick any floor square. */ if (scatter) { for (i = 0; i < 200; i++) { /* Pick a totally random spot. */ y = randint0(DUNGEON_HGT); x = randint0(DUNGEON_WID); /* Must be an empty floor. */ if (!cave_empty_bold(y, x)) continue; /* Place the object there. */ if (obj_success) drop_near(i_ptr, -1, y, x); /* Done. */ break; } } /* Normally, drop object near the chest. */ else if (obj_success) drop_near(i_ptr, -1, y, x); } /* Clear this global variable, to avoid messing up object generation. */ required_tval = 0; /* Reset the object level */ object_level = p_ptr->depth; /* No longer opening a chest */ opening_chest = FALSE; /* Empty */ o_ptr->pval = 0; /* Known */ object_known(o_ptr); }
bool quest_poison_gen_hook(char *fmt) { int cy = 1, cx = 1, x, y, try = 10000, r_idx; bool (*old_get_mon_num_hook)(int r_idx); if (cquest.status != QUEST_STATUS_TAKEN) return FALSE; if (p_ptr->wilderness_y != wild_locs[cquest.data[0]][0]) return FALSE; if (p_ptr->wilderness_x != wild_locs[cquest.data[0]][1]) return FALSE; if (p_ptr->wild_mode) return FALSE; /* Find a good position */ while (try) { /* Get a random spot */ cy = randint(cur_hgt - 24) + 22; cx = randint(cur_wid - 34) + 32; /* Is it a good spot ? */ if (cave_empty_bold(cy, cx)) break; /* One less try */ try--; } /* Place the baddies */ /* Backup the old hook */ old_get_mon_num_hook = get_mon_num_hook; /* Require "okay" monsters */ get_mon_num_hook = create_molds_hook; /* Prepare allocation table */ get_mon_num_prep(); /* Pick a monster, using the level calculation */ for (x = cx - 25; x <= cx + 25; x++) for (y = cy - 25; y <= cy + 25; y++) { if (!in_bounds(y, x)) continue; if (distance(cy, cx, y, x) > 25) continue; if (magik(80) && ((cave[y][x].feat == FEAT_DEEP_WATER) || (cave[y][x].feat == FEAT_SHAL_WATER))) cave_set_feat(y, x, FEAT_TAINTED_WATER); if (distance(cy, cx, y, x) > 10) continue; if (magik(60)) { int m_idx; r_idx = get_mon_num(30); m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY); /* Sometimes make it up some levels */ if (magik(80) && m_idx) { monster_type *m_ptr = &m_list[m_idx]; if (m_ptr->level < p_ptr->lev) { m_ptr->exp = MONSTER_EXP(m_ptr->level + randint(p_ptr->lev - m_ptr->level)); monster_check_experience(m_idx, TRUE); } } } } /* Reset restriction */ get_mon_num_hook = old_get_mon_num_hook; /* Prepare allocation table */ get_mon_num_prep(); return FALSE; } bool quest_poison_finish_hook(char *fmt) { object_type forge, *q_ptr; s32b q_idx; q_idx = get_next_arg(fmt); if (q_idx != QUEST_POISON) return FALSE; c_put_str(TERM_YELLOW, "The water is clean again! Thank you so much.", 8, 0); c_put_str(TERM_YELLOW, "The beautiful Mallorns are safe. Take this as a proof of our gratitude.", 9, 0); q_ptr = &forge; object_prep(q_ptr, lookup_kind(TV_DRAG_ARMOR, SV_DRAGON_BLUE)); q_ptr->found = OBJ_FOUND_REWARD; q_ptr->number = 1; q_ptr->name2 = EGO_ELVENKIND; apply_magic(q_ptr, 1, FALSE, FALSE, FALSE); object_aware(q_ptr); object_known(q_ptr); q_ptr->ident |= IDENT_STOREB; (void)inven_carry(q_ptr, FALSE); /* Continue the plot */ *(quest[q_idx].plot) = QUEST_NULL; del_hook(HOOK_QUEST_FINISH, quest_poison_finish_hook); process_hooks_restart = TRUE; return TRUE; }
/* * Become unaware of objects, monster memory, and the map */ static void do_cmd_wiz_forget(void) { int i; /* Forget info about objects on the map */ for (i = 1; i < o_max; i++) { object_type *o_ptr = &o_list[i]; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; // identify non-special non-artefact weapons/armour switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_ARROW: case TV_MAIL: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: case TV_LIGHT: { if (!o_ptr->name1 && !o_ptr->name2) { /* Identify it */ object_aware(o_ptr); object_known(o_ptr); break; } } default: { if (!(k_ptr->flags3 & (TR3_EASY_KNOW))) { o_ptr->ident &= ~(IDENT_KNOWN); } } } /* Hack -- Clear the "empty" flag */ o_ptr->ident &= ~(IDENT_EMPTY); // re pseudo id pseudo_id(o_ptr); } /* Forget info about carried objects */ for (i = 0; i < INVEN_TOTAL; i++) { object_type *o_ptr = &inventory[i]; object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; // identify non-special non-artefact weapons/armour switch (o_ptr->tval) { case TV_DIGGING: case TV_HAFTED: case TV_POLEARM: case TV_SWORD: case TV_BOW: case TV_ARROW: case TV_MAIL: case TV_SOFT_ARMOR: case TV_SHIELD: case TV_HELM: case TV_CROWN: case TV_CLOAK: case TV_GLOVES: case TV_BOOTS: case TV_LIGHT: { if (!o_ptr->name1 && !o_ptr->name2) { /* Identify it */ object_aware(o_ptr); object_known(o_ptr); break; } } default: { if (!(k_ptr->flags3 & (TR3_EASY_KNOW))) { o_ptr->ident &= ~(IDENT_KNOWN); } } } /* Hack -- Clear the "empty" flag */ o_ptr->ident &= ~(IDENT_EMPTY); // re pseudo id pseudo_id(o_ptr); } /* Reset the object kinds */ for (i = 1; i < z_info->k_max; i++) { object_kind *k_ptr = &k_info[i]; /* Reset "tried" */ k_ptr->tried = FALSE; /* Reset "aware" */ k_ptr->aware = FALSE; } /* Reset the special objects */ for (i = 1; i < z_info->e_max; i++) { ego_item_type *e_ptr = &e_info[i]; /* Reset "aware" */ e_ptr->aware = FALSE; } /* Forget encountered monsters */ for (i = 1; i < mon_max; i++) { monster_type *m_ptr = &mon_list[i]; m_ptr->encountered = FALSE; } /* Reset the monster memory */ for (i = 1; i < z_info->r_max; i++) { monster_lore *l_ptr = &l_list[i]; WIPE(l_ptr, monster_lore); } /* Mega-Hack -- Forget the map */ wiz_dark(); // lose all spare experience //lose_exp(10000); // clear the cheat flags p_ptr->noscore = 0x0000; /* Forget turns */ turn = 1; playerturn = 1; // forget all messages -- currently a bit buggy messages_init(); // clear target target_set_monster(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Combine / Reorder the pack (later) */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); /* Window stuff */ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER_0); }
/* * Create a spoiler file for artifacts */ static void spoil_artifact(void) { int i, j; object_type forge; object_type *q_ptr; const bool old_spoil_art = spoil_art; const bool old_spoil_base = spoil_base; const bool old_cheat_item = cheat_item; /* Use full spoilers, but no cheating. */ spoil_art = spoil_base = TRUE; cheat_item = FALSE; /* Dump the header */ print_header(); /* List the artifacts by tval */ for (i = 0; group_artifact[i].idx; i++) { /* Write out the group title */ if (group_artifact[i].str) { spoiler_blanklines(2); spoiler_underline(group_artifact[i].str); spoiler_blanklines(1); } /* Now search through all of the artifacts */ for (j = 1; j < MAX_A_IDX; ++j) { artifact_type *a_ptr = &a_info[j]; /* We only want objects in the current group */ if (k_info[a_ptr->k_idx].tval != group_artifact[i].idx) continue; /* Get local object */ q_ptr = &forge; /* Wipe the object */ object_wipe(q_ptr); /* Attempt to "forge" the artifact */ if (!make_fake_artifact(q_ptr, j)) continue; /* Know most things about the object. */ object_known(q_ptr); my_fprintf(fff, "%v\n", object_desc_f3, q_ptr, OD_ART | OD_SHOP, 1); /* Describe the artifact in a relatively brief way. */ identify_fully_file(q_ptr, fff, TRUE); /* Provide some allocation data. */ fprintf(fff, " Level %d", a_ptr->level); if (a_ptr->level2 && a_ptr->level2 != a_ptr->level) { fprintf(fff, "/%d", a_ptr->level2); } fprintf(fff, ", Rarity %d, %d.%d lbs, %ld Gold\n", a_ptr->rarity, a_ptr->weight/10, a_ptr->weight%10, a_ptr->cost); } } /* Reset spoilers. */ spoil_art = old_spoil_art; spoil_base = old_spoil_base; cheat_item = old_cheat_item; }
/** * Hack - Know inventory and home items upon death */ static void death_knowledge(void) { int i, which = 0; object_type *o_ptr; store_type *st_ptr = NULL; /* Get the store number of the home */ if (OPT(adult_dungeon)) which = NUM_TOWNS_SMALL * 4 + STORE_HOME; else { for (i = 0; i < NUM_TOWNS; i++) { /* Found the town */ if (p_ptr->home == towns[i]) { which += (i < NUM_TOWNS_SMALL ? 3 : STORE_HOME); break; } /* Next town */ else which += (i < NUM_TOWNS_SMALL ? MAX_STORES_SMALL : MAX_STORES_BIG); } } /* Hack -- Know everything in the inven/equip */ for (i = 0; i < ALL_INVEN_TOTAL; i++) { o_ptr = &p_ptr->inventory[i]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Aware and Known */ object_aware(o_ptr); object_known(o_ptr); /* Fully known */ cf_union(o_ptr->id_curse, o_ptr->flags_curse); } /* Thralls sometimes (often!) don't have a home */ if (p_ptr->home) { /* Activate the store */ st_ptr = &store[which]; /* Hack -- Know everything in the home */ for (i = 0; i < st_ptr->stock_num; i++) { o_ptr = &st_ptr->stock[i]; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Aware and Known */ object_aware(o_ptr); object_known(o_ptr); /* Fully known */ cf_union(o_ptr->id_curse, o_ptr->flags_curse); } } history_unmask_unknown(); /* Hack -- Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Handle stuff */ handle_stuff(); }