/** * Housekeeping after the processing of a player command */ static void process_player_cleanup(void) { int i; /* Significant */ if (player->upkeep->energy_use) { /* Use some energy */ player->energy -= player->upkeep->energy_use; /* Increment the total energy counter */ player->total_energy += player->upkeep->energy_use; /* Do nothing else if player has auto-dropped stuff */ if (!player->upkeep->dropping) { /* Hack -- constant hallucination */ if (player->timed[TMD_IMAGE]) player->upkeep->redraw |= (PR_MAP); /* Shimmer multi-hued monsters */ for (i = 1; i < cave_monster_max(cave); i++) { struct monster *mon = cave_monster(cave, i); if (!mon->race) continue; if (!rf_has(mon->race->flags, RF_ATTR_MULTI)) continue; square_light_spot(cave, mon->fy, mon->fx); } /* Clear NICE flag, and show marked monsters */ for (i = 1; i < cave_monster_max(cave); i++) { struct monster *mon = cave_monster(cave, i); mflag_off(mon->mflag, MFLAG_NICE); if (mflag_has(mon->mflag, MFLAG_MARK)) { if (!mflag_has(mon->mflag, MFLAG_SHOW)) { mflag_off(mon->mflag, MFLAG_MARK); update_mon(mon, cave, false); } } } } } /* Clear SHOW flag and player drop status */ for (i = 1; i < cave_monster_max(cave); i++) { struct monster *mon = cave_monster(cave, i); mflag_off(mon->mflag, MFLAG_SHOW); } player->upkeep->dropping = false; /* Hack - update needed first because inventory may have changed */ update_stuff(player); redraw_stuff(player); }
/** * Clear 'moved' status from all monsters. * * Clear noise if appropriate. */ void reset_monsters(void) { int i; struct monster *mon; /* Process the monsters (backwards) */ for (i = cave_monster_max(cave) - 1; i >= 1; i--) { /* Access the monster */ mon = cave_monster(cave, i); /* Monster is ready to go again */ mflag_off(mon->mflag, MFLAG_HANDLED); } }
/** * Clear 'moved' status from all monsters. * * Clear noise if appropriate. */ void reset_monsters(void) { int i; monster_type *m_ptr; /* Process the monsters (backwards) */ for (i = cave_monster_max(cave) - 1; i >= 1; i--) { /* Access the monster */ m_ptr = cave_monster(cave, i); /* Monster is ready to go again */ mflag_off(m_ptr->mflag, MFLAG_HANDLED); } }
/** * Determine whether a monster is active or passive */ static bool monster_check_active(struct chunk *c, struct monster *mon) { /* Character is inside scanning range */ if (mon->cdis <= mon->race->aaf) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster is hurt */ else if (mon->hp < mon->maxhp) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster can "see" the player (checked backwards) */ else if (square_isview(c, mon->fy, mon->fx)) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Monster can "smell" the player from far away (flow) */ else if (monster_can_flow(c, mon)) mflag_on(mon->mflag, MFLAG_ACTIVE); /* Otherwise go passive */ else mflag_off(mon->mflag, MFLAG_ACTIVE); return mflag_has(mon->mflag, MFLAG_ACTIVE) ? true : false; }
/** * Determine whether a monster is active or passive */ static bool monster_check_active(struct chunk *c, struct monster *mon) { if ((mon->cdis <= mon->race->hearing) && monster_passes_walls(mon)) { /* Character is inside scanning range, monster can go straight there */ mflag_on(mon->mflag, MFLAG_ACTIVE); } else if (mon->hp < mon->maxhp) { /* Monster is hurt */ mflag_on(mon->mflag, MFLAG_ACTIVE); } else if (square_isview(c, mon->fy, mon->fx)) { /* Monster can "see" the player (checked backwards) */ mflag_on(mon->mflag, MFLAG_ACTIVE); } else if (monster_can_hear(c, mon)) { /* Monster can hear the player */ mflag_on(mon->mflag, MFLAG_ACTIVE); } else if (monster_can_smell(c, mon)) { /* Monster can smell the player */ mflag_on(mon->mflag, MFLAG_ACTIVE); } else { /* Otherwise go passive */ mflag_off(mon->mflag, MFLAG_ACTIVE); } return mflag_has(mon->mflag, MFLAG_ACTIVE) ? true : false; }
/** * Attempts to place a monster of the given race at the given location. * * If `sleep` is true, the monster is placed with its default sleep value, * which is given in monster.txt. * * `origin` is the item origin to use for any monster drops (e.g. ORIGIN_DROP, * ORIGIN_DROP_PIT, etc.) * * To give the player a sporting chance, some especially dangerous * monsters are marked as "FORCE_SLEEP" in monster.txt, which will * cause them to be placed with low energy. This helps ensure that * if such a monster suddenly appears in line-of-sight (due to a * summon, for instance), the player gets a chance to move before * they do. * * This routine refuses to place out-of-depth "FORCE_DEPTH" monsters. * * This is the only function which may place a monster in the dungeon, * except for the savefile loading code, which calls place_monster() * directly. */ static bool place_new_monster_one(struct chunk *c, int y, int x, struct monster_race *race, bool sleep, byte origin) { int i; struct monster *mon; struct monster monster_body; assert(square_in_bounds(c, y, x)); assert(race && race->name); /* Not where monsters already are */ if (square_monster(c, y, x)) return false; /* Not where the player already is */ if ((player->py == y) && (player->px == x)) return false; /* Prevent monsters from being placed where they cannot walk, but allow other feature types */ if (!square_is_monster_walkable(c, y, x)) return false; /* No creation on glyph of warding */ if (square_iswarded(c, y, x)) return false; /* "unique" monsters must be "unique" */ if (rf_has(race->flags, RF_UNIQUE) && race->cur_num >= race->max_num) return (false); /* Depth monsters may NOT be created out of depth */ if (rf_has(race->flags, RF_FORCE_DEPTH) && player->depth < race->level) return (false); /* Add to level feeling, note uniques for cheaters */ c->mon_rating += race->level * race->level; /* Check out-of-depth-ness */ if (race->level > c->depth) { if (rf_has(race->flags, RF_UNIQUE)) { /* OOD unique */ if (OPT(player, cheat_hear)) msg("Deep unique (%s).", race->name); } else { /* Normal monsters but OOD */ if (OPT(player, cheat_hear)) msg("Deep monster (%s).", race->name); } /* Boost rating by power per 10 levels OOD */ c->mon_rating += (race->level - c->depth) * race->level * race->level; } else if (rf_has(race->flags, RF_UNIQUE) && OPT(player, cheat_hear)) msg("Unique (%s).", race->name); /* Get local monster */ mon = &monster_body; /* Clean out the monster */ memset(mon, 0, sizeof(struct monster)); /* Save the race */ mon->race = race; /* Enforce sleeping if needed */ if (sleep && race->sleep) { int val = race->sleep; mon->m_timed[MON_TMD_SLEEP] = ((val * 2) + randint1(val * 10)); } /* Uniques get a fixed amount of HP */ if (rf_has(race->flags, RF_UNIQUE)) mon->maxhp = race->avg_hp; else { mon->maxhp = mon_hp(race, RANDOMISE); mon->maxhp = MAX(mon->maxhp, 1); } /* And start out fully healthy */ mon->hp = mon->maxhp; /* Extract the monster base speed */ mon->mspeed = race->speed; /* Hack -- small racial variety */ if (!rf_has(race->flags, RF_UNIQUE)) { /* Allow some small variation per monster */ i = turn_energy(race->speed) / 10; if (i) mon->mspeed += rand_spread(0, i); } /* Give a random starting energy */ mon->energy = (byte)randint0(50); /* Force monster to wait for player */ if (rf_has(race->flags, RF_FORCE_SLEEP)) mflag_on(mon->mflag, MFLAG_NICE); /* Radiate light? */ if (rf_has(race->flags, RF_HAS_LIGHT)) player->upkeep->update |= PU_UPDATE_VIEW; /* Is this obviously a monster? (Mimics etc. aren't) */ if (rf_has(race->flags, RF_UNAWARE)) mflag_on(mon->mflag, MFLAG_CAMOUFLAGE); else mflag_off(mon->mflag, MFLAG_CAMOUFLAGE); /* Set the color if necessary */ if (rf_has(race->flags, RF_ATTR_RAND)) mon->attr = randint1(BASIC_COLORS - 1); /* Place the monster in the dungeon */ if (!place_monster(c, y, x, mon, origin)) return (false); /* Success */ return (true); }