/* Destroy Doors (and traps) */ static void project_feature_handler_KILL_DOOR(project_feature_handler_context_t *context) { const int x = context->x; const int y = context->y; /* Destroy all doors and traps */ if (square_isplayertrap(cave, y, x) || square_isdoor(cave, y, x)) { /* Check line of sight */ if (square_isview(cave, y, x)) { /* Message */ msg("There is a bright flash of light!"); context->obvious = true; /* Visibility change */ if (square_isdoor(cave, y, x)) player->upkeep->update |= (PU_UPDATE_VIEW | PU_MONSTERS); /* Forget the door */ square_forget(cave, y, x); } /* Destroy the feature */ if (square_isdoor(cave, y, x)) square_destroy_door(cave, y, x); else square_destroy_trap(cave, y, x); } }
/** * True if the square is an untrapped floor square without items. */ bool square_canputitem(struct chunk *c, int y, int x) { if (!square_isfloor(c, y, x)) return FALSE; if (square_iswarded(c, y, x) || square_isplayertrap(c, y, x)) return FALSE; return !square_object(c, y, x); }
/** * Reveal some of the player traps in a square */ bool square_reveal_trap(struct chunk *c, int y, int x, bool always, bool domsg) { int found_trap = 0; struct trap *trap = square_trap(c, y, x); /* Check there is a player trap */ if (!square_isplayertrap(c, y, x)) return false; /* Scan the grid */ while (trap) { /* Skip non-player traps */ if (!trf_has(trap->flags, TRF_TRAP)) { trap = trap->next; continue; } /* Skip traps the player doesn't notice */ if (!always && player->state.skills[SKILL_SEARCH] < trap->power) { trap = trap->next; continue; } /* Trap is invisible */ if (!trf_has(trap->flags, TRF_VISIBLE)) { /* See the trap */ trf_on(trap->flags, TRF_VISIBLE); square_memorize(c, y, x); /* We found a trap */ found_trap++; } trap = trap->next; } /* We found at least one trap */ if (found_trap) { /* We want to talk about it */ if (domsg) { if (found_trap == 1) msg("You have found a trap."); else msg("You have found %d traps.", found_trap); } /* Memorize */ square_memorize(c, y, x); /* Redraw */ square_light_spot(c, y, x); } /* Return true if we found any traps */ return (found_trap != 0); }
/** * Reveal some of the player traps in a square */ bool square_reveal_trap(struct chunk *c, int y, int x, int chance, bool domsg) { int found_trap = 0; struct trap *trap = c->squares[y][x].trap; /* Check there is a player trap */ if (!square_isplayertrap(c, y, x)) return FALSE; /* Scan the grid */ while (trap) { /* Skip non-player traps */ if (!trf_has(trap->flags, TRF_TRAP)) { trap = trap->next; continue; } /* Trap is invisible */ if (!trf_has(trap->flags, TRF_VISIBLE)) { /* See the trap */ trf_on(trap->flags, TRF_VISIBLE); sqinfo_on(c->squares[y][x].info, SQUARE_MARK); /* We found a trap */ found_trap++; /* If chance is < 100, check for further looking */ if ((chance < 100) && (randint1(100) > chance)) break; } trap = trap->next; } /* We found at least one trap */ if (found_trap) { /* We want to talk about it */ if (domsg) { if (found_trap == 1) msg("You have found a trap."); else msg("You have found %d traps.", found_trap); } /* Memorize */ sqinfo_on(c->squares[y][x].info, SQUARE_MARK); /* Redraw */ square_light_spot(c, y, x); } /* Return TRUE if we found any traps */ return (found_trap != 0); }
/** * True if the square is a known player trap. */ bool square_isknowntrap(struct chunk *c, int y, int x) { return square_isvisibletrap(c, y, x) && square_isplayertrap(c, y, x); }
/** * True if the square is an unknown player trap (it will appear as a floor tile) */ bool square_issecrettrap(struct chunk *c, int y, int x) { return !square_isvisibletrap(c, y, x) && square_isplayertrap(c, y, x); }
/** * True if the square is empty (an open square without any items). */ bool square_isempty(struct chunk *c, int y, int x) { if (square_isplayertrap(c, y, x)) return FALSE; return square_isopen(c, y, x) && !square_object(c, y, x); }
/** * Find a grid near the given one for an object to fall on * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. * * If no appropriate grid is found, the given grid is unchanged */ static void drop_find_grid(struct object *drop, int *y, int *x) { int best_score = -1; int best_y = *y; int best_x = *x; int i, dy, dx; struct object *obj; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { for (dx = -3; dx <= 3; dx++) { bool combine = false; int dist = (dy * dy) + (dx * dx); int ty = *y + dy; int tx = *x + dx; int num_shown = 0; int num_ignored = 0; int score; /* Lots of reasons to say no */ if ((dist > 10) || !square_in_bounds_fully(cave, ty, tx) || !los(cave, *y, *x, ty, tx) || !square_isfloor(cave, ty, tx) || square_isplayertrap(cave, ty, tx) || square_iswarded(cave, ty, tx)) continue; /* Analyse the grid for carrying the new object */ for (obj = square_object(cave, ty, tx); obj; obj = obj->next) { /* Check for possible combination */ if (object_similar(obj, drop, OSTACK_FLOOR)) combine = true; /* Count objects */ if (!ignore_item_ok(obj)) num_shown++; else num_ignored++; } if (!combine) num_shown++; /* Disallow if the stack size is too big */ if ((OPT(player, birth_stacking) && (num_shown > 1)) || ((num_shown + num_ignored) > z_info->floor_size && !floor_get_oldest_ignored(ty, tx))) continue; /* Score the location based on how close and how full the grid is */ score = 1000 - (dist + num_shown * 5); if ((score < best_score) || ((score == best_score) && one_in_(2))) continue; best_score = score; best_y = ty; best_x = tx; } } /* Return if we have a score, otherwise fail or try harder for artifacts */ if (best_score >= 0) { *y = best_y; *x = best_x; return; } else if (!drop->artifact) { return; } for (i = 0; i < 2000; i++) { /* Start bouncing from grid to grid, stopping if we find an empty one */ if (i < 1000) { best_y = rand_spread(best_y, 1); best_x = rand_spread(best_x, 1); } else { /* Now go to purely random locations */ best_y = randint0(cave->height); best_x = randint0(cave->width); } if (square_canputitem(cave, best_y, best_x)) { *y = best_y; *x = best_x; return; } } }
/** * Let an object fall to the ground at or near a location. * * The initial location is assumed to be "square_in_bounds_fully(cave, )". * * This function takes a parameter "chance". This is the percentage * chance that the item will "disappear" instead of drop. If the object * has been thrown, then this is the chance of disappearance on contact. * * This function will produce a description of a drop event under the player * when "verbose" is true. * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. * * Objects which fail to be carried by the floor are deleted. This function * attempts to add successfully dropped objects to, and to remove failures * from, the object list (as dropped items may or may not be already listed). */ void drop_near(struct chunk *c, struct object *dropped, int chance, int y, int x, bool verbose) { int i, k, n, d, s; int bs, bn; int by, bx; int dy, dx; int ty, tx; struct object *obj; char o_name[80]; bool flag = false; /* Only called in the current level */ assert(c == cave); /* Describe object */ object_desc(o_name, sizeof(o_name), dropped, ODESC_BASE); /* Handle normal "breakage" */ if (!dropped->artifact && (randint0(100) < chance)) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "breaks", "break")); /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Score */ bs = -1; /* Picker */ bn = 0; /* Default */ by = y; bx = x; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { for (dx = -3; dx <= 3; dx++) { bool comb = false; /* Calculate actual distance */ d = (dy * dy) + (dx * dx); /* Ignore distant grids */ if (d > 10) continue; /* Location */ ty = y + dy; tx = x + dx; /* Skip illegal grids */ if (!square_in_bounds_fully(c, ty, tx)) continue; /* Require line of sight */ if (!los(c, y, x, ty, tx)) continue; /* Require floor space */ if (!square_isfloor(c, ty, tx)) continue; /* Require no trap or rune */ if (square_isplayertrap(c, ty, tx) || square_iswarded(c, ty, tx)) continue; /* No objects */ k = 0; n = 0; /* Scan objects in that grid */ for (obj = square_object(c, ty, tx); obj; obj = obj->next) { /* Check for possible combination */ if (object_similar(obj, dropped, OSTACK_FLOOR)) comb = true; /* Count objects */ if (!ignore_item_ok(obj)) k++; else n++; } /* Add new object */ if (!comb) k++; /* Option -- disallow stacking */ if (OPT(birth_no_stacking) && (k > 1)) continue; /* Paranoia? */ if ((k + n) > z_info->floor_size && !floor_get_oldest_ignored(ty, tx)) continue; /* Calculate score */ s = 1000 - (d + k * 5); /* Skip bad values */ if (s < bs) continue; /* New best value */ if (s > bs) bn = 0; /* Apply the randomizer to equivalent values */ if ((++bn >= 2) && (randint0(bn) != 0)) continue; /* Keep score */ bs = s; /* Track it */ by = ty; bx = tx; /* Okay */ flag = true; } } /* Handle lack of space */ if (!flag && !dropped->artifact) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "disappears", "disappear")); /* Debug */ if (player->wizard) msg("Breakage (no floor space)."); /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Find a grid */ for (i = 0; !flag; i++) { /* Bounce around */ if (i < 1000) { ty = rand_spread(by, 1); tx = rand_spread(bx, 1); } else { /* Random locations */ ty = randint0(c->height); tx = randint0(c->width); } /* Require floor space */ if (!square_canputitem(c, ty, tx)) continue; /* Bounce to that location */ by = ty; bx = tx; /* Okay */ flag = true; } /* Give it to the floor */ if (!floor_carry(c, by, bx, dropped, false)) { /* Message */ msg("The %s %s.", o_name, VERB_AGREEMENT(dropped->number, "disappears", "disappear")); /* Debug */ if (player->wizard) msg("Breakage (too many objects)."); if (dropped->artifact) dropped->artifact->created = false; /* Failure */ if (dropped->known) { delist_object(cave_k, dropped->known); object_delete(&dropped->known); } delist_object(c, dropped); object_delete(&dropped); return; } /* Sound */ sound(MSG_DROP); /* Message when an object falls under the player */ if (verbose && (c->squares[by][bx].mon < 0)) /* Check the item still exists and isn't ignored */ if (c->objects[dropped->oidx] && !ignore_item_ok(dropped)) msg("You feel something roll beneath your feet."); }
void square_disable_trap(struct chunk *c, int y, int x) { if (!square_isplayertrap(c, y, x)) return; square_set_trap_timeout(c, y, x, false, -1, 10); }
/** * Place random stairs at (x, y). * \param c current chunk * \param y * \param x co-ordinates */ void place_random_stairs(struct chunk *c, int y, int x) { int feat = randint0(100) < 50 ? FEAT_LESS : FEAT_MORE; if (square_canputitem(c, y, x) && !square_isplayertrap(c, y, x)) place_stairs(c, y, x, feat); }