/** * Check if the monster can occupy a grid safely */ static bool monster_hates_grid(struct chunk *c, struct monster *mon, int y, int x) { /* Only some creatures can handle damaging terrain */ if (square_isdamaging(c, y, x) && !rf_has(mon->race->flags, square_feat(c, y, x)->resist_flag)) { return true; } return false; }
/** * This will push objects off a square. * * The methodology is to load all objects on the square into a queue. Replace * the previous square with a type that does not allow for objects. Drop the * objects. Last, put the square back to its original type. */ void push_object(int y, int x) { /* Save the original terrain feature */ struct feature *feat_old = square_feat(cave, y, x); struct object *obj = square_object(cave, y, x); struct queue *queue = q_new(z_info->floor_size); bool glyph = square_iswarded(cave, y, x); /* Push all objects on the square, stripped of pile info, into the queue */ while (obj) { struct object *next = obj->next; q_push_ptr(queue, obj); /* Orphan the object */ obj->next = NULL; obj->prev = NULL; obj->iy = 0; obj->ix = 0; /* Next object */ obj = next; } /* Disassociate the objects from the square */ cave->squares[y][x].obj = NULL; /* Set feature to an open door */ square_force_floor(cave, y, x); square_add_door(cave, y, x, false); /* Drop objects back onto the floor */ while (q_len(queue) > 0) { /* Take object from the queue */ obj = q_pop_ptr(queue); /* Drop the object */ drop_near(cave, &obj, 0, y, x, false); } /* Reset cave feature and rune if needed */ square_set_feat(cave, y, x, feat_old->fidx); if (glyph) square_add_ward(cave, y, x); q_free(queue); }
/** * Determine if a cave grid is allowed to have player traps in it. */ bool square_player_trap_allowed(struct chunk *c, int y, int x) { /* * We currently forbid multiple traps in a grid under normal conditions. * If this changes, various bits of code elsewhere will have to change too. */ if (square_istrap(c, y, x)) return false; /* We currently forbid traps in a grid with objects. */ if (square_object(c, y, x)) return false; /* Check the feature trap flag */ return (tf_has(square_feat(c, y, x)->flags, TF_TRAP)); }
/** * Choose a "safe" location near a monster for it to run toward. * * A location is "safe" if it can be reached quickly and the player * is not able to fire into it (it isn't a "clean shot"). So, this will * cause monsters to "duck" behind walls. Hopefully, monsters will also * try to run towards corridor openings if they are in a room. * * This function may take lots of CPU time if lots of monsters are fleeing. * * Return true if a safe location is available. */ static bool get_move_find_safety(struct chunk *c, struct monster *mon) { int fy = mon->fy; int fx = mon->fx; int py = player->py; int px = player->px; int i, y, x, dy, dx, d, dis; int gy = 0, gx = 0, gdis = 0; const int *y_offsets; const int *x_offsets; /* Start with adjacent locations, spread further */ for (d = 1; d < 10; d++) { /* Get the lists of points with a distance d from (fx, fy) */ y_offsets = dist_offsets_y[d]; x_offsets = dist_offsets_x[d]; /* Check the locations */ for (i = 0, dx = x_offsets[0], dy = y_offsets[0]; dx != 0 || dy != 0; i++, dx = x_offsets[i], dy = y_offsets[i]) { y = fy + dy; x = fx + dx; /* Skip illegal locations */ if (!square_in_bounds_fully(c, y, x)) continue; /* Skip locations in a wall */ if (!square_ispassable(c, y, x)) continue; /* Ignore too-distant grids */ if (c->noise.grids[y][x] > c->noise.grids[fy][fx] + 2 * d) continue; /* Ignore damaging terrain if they can't handle it */ if (square_isdamaging(c, y, x) && !rf_has(mon->race->flags, square_feat(c, y, x)->resist_flag)) continue; /* Check for absence of shot (more or less) */ if (!square_isview(c, y, x)) { /* Calculate distance from player */ dis = distance(loc(x, y), loc(px, py)); /* Remember if further than previous */ if (dis > gdis) { gy = y; gx = x; gdis = dis; } } } /* Check for success */ if (gdis > 0) { /* Good location */ mon->target.grid = loc(gx, gy); return (true); } } /* No safe place */ return (false); }