/*
+ * Set the target of counter attack
+ */
+void set_target(monster_type *m_ptr, int y, int x)
+{
+ m_ptr->target_y = y;
+ m_ptr->target_x = x;
+}
+
+/*
+ * Reset the target of counter attack
+ */
+void reset_target(monster_type *m_ptr)
+{
+ set_target(m_ptr, 0, 0);
+}
+
+/*
* Delete a monster by index.
*
* When a monster is deleted, all of its objects are deleted.
/* Hack -- Reduce the racial counter */
- r_ptr->cur_num--;
+ if (m_ptr->mflag2 & MFLAG_CHAMELEON)
+ {
+ if (r_ptr->flags1 & RF1_UNIQUE)
+ r_info[MON_CHAMELEON_K].cur_num--;
+ else
+ r_info[MON_CHAMELEON].cur_num--;
+ }
+ else
+ {
+ r_ptr->cur_num--;
+ }
/* Hack -- count the number of "reproducers" */
if (r_ptr->flags2 & (RF2_MULTIPLY)) num_repro--;
if (r_ptr->flags1 & (RF1_UNIQUE)) chance = 100;
/* All monsters get a saving throw */
- if (rand_int(100) < chance) continue;
+ if (randint0(100) < chance) continue;
/* Delete the monster */
delete_monster_idx(i);
/* Mega-Hack -- preserve Unique's XXX XXX XXX */
/* Hack -- Reduce the racial counter */
- r_ptr->cur_num--;
+ if (m_ptr->mflag2 & MFLAG_CHAMELEON)
+ {
+ if (r_ptr->flags1 & RF1_UNIQUE)
+ r_info[MON_CHAMELEON_K].cur_num = 0;
+ else
+ r_info[MON_CHAMELEON].cur_num = 0;
+ }
+ else
+ r_ptr->cur_num = 0;
/* Monster is gone */
cave[m_ptr->fy][m_ptr->fx].m_idx = 0;
static bool summon_specific_aux(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
- bool okay = FALSE;
+ int okay = FALSE;
/* Check our requirements */
switch (summon_specific_type)
case SUMMON_DEMON:
{
- okay = (bool)(r_ptr->flags3 & RF3_DEMON);
+ okay = (r_ptr->flags3 & RF3_DEMON);
break;
}
case SUMMON_UNDEAD:
{
- okay = (bool)(r_ptr->flags3 & RF3_UNDEAD);
+ okay = (r_ptr->flags3 & RF3_UNDEAD);
break;
}
case SUMMON_DRAGON:
{
- okay = (bool)(r_ptr->flags3 & RF3_DRAGON);
+ okay = (r_ptr->flags3 & RF3_DRAGON);
break;
}
case SUMMON_ANIMAL:
{
- okay = (bool)(r_ptr->flags3 & (RF3_ANIMAL));
+ okay = (r_ptr->flags3 & (RF3_ANIMAL));
break;
}
okay = (r_idx == MON_LOUSE);
break;
}
+
+ case SUMMON_GUARDIANS:
+ {
+ okay = (r_ptr->flags7 & RF7_GUARDIAN);
+ break;
+ }
+
+ case SUMMON_KNIGHTS:
+ {
+ okay = ((r_idx == MON_NOV_PALADIN) ||
+ (r_idx == MON_NOV_PALADIN_G) ||
+ (r_idx == MON_PALADIN) ||
+ (r_idx == MON_W_KNIGHT) ||
+ (r_idx == MON_ULTRA_PALADIN) ||
+ (r_idx == MON_KNI_TEMPLAR));
+ break;
+ }
}
/* Result */
- return (okay);
+ /* Since okay is int, "return (okay);" is not correct. */
+ return (bool)(okay ? TRUE : FALSE);
}
/* Scan the allocation table */
for (i = 0; i < alloc_race_size; i++)
{
+ monster_race *r_ptr;
+
/* Get the entry */
alloc_entry *entry = &alloc_race_table[i];
- /* Accept monsters which pass the restriction, if any */
- if ((!get_mon_num_hook || (*get_mon_num_hook)(entry->index)) &&
- (!get_mon_num2_hook || (*get_mon_num2_hook)(entry->index)))
+ entry->prob2 = 0;
+ r_ptr = &r_info[entry->index];
+
+ /* Skip monsters which don't pass the restriction */
+ if ((get_mon_num_hook && !((*get_mon_num_hook)(entry->index))) ||
+ (get_mon_num2_hook && !((*get_mon_num2_hook)(entry->index))))
+ continue;
+
+ if (!p_ptr->inside_battle && !chameleon_change &&
+ summon_specific_type != SUMMON_GUARDIANS)
{
- /* Accept this monster */
- entry->prob2 = entry->prob1;
+ /* Hack -- don't create questors */
+ if (r_ptr->flags1 & RF1_QUESTOR)
+ continue;
- if (dun_level && (!p_ptr->inside_quest || p_ptr->inside_quest < MIN_RANDOM_QUEST) && !restrict_monster_to_dungeon(entry->index) && !p_ptr->inside_battle)
- {
- int hoge = entry->prob2 * d_info[dungeon_type].special_div;
- entry->prob2 = hoge / 64;
- if (rand_int(64) < (hoge & 0x3f)) entry->prob2++;
- }
+ if (r_ptr->flags7 & RF7_GUARDIAN)
+ continue;
+
+ /* Depth Monsters never appear out of depth */
+ if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) &&
+ (r_ptr->level > dun_level))
+ continue;
}
- /* Do not use this monster */
- else
+ /* Accept this monster */
+ entry->prob2 = entry->prob1;
+
+ if (dun_level && (!p_ptr->inside_quest || p_ptr->inside_quest < MIN_RANDOM_QUEST) && !restrict_monster_to_dungeon(entry->index) && !p_ptr->inside_battle)
{
- /* Decline this monster */
- entry->prob2 = 0;
+ int hoge = entry->prob2 * d_info[dungeon_type].special_div;
+ entry->prob2 = hoge / 64;
+ if (randint0(64) < (hoge & 0x3f)) entry->prob2++;
}
}
if (level > MAX_DEPTH - 1) level = MAX_DEPTH - 1;
- if ((dungeon_turn > hoge*10000L) && !level)
+ if ((dungeon_turn > hoge*(TURNS_PER_TICK*500L)) && !level)
{
- pls_kakuritu = MAX(2, NASTY_MON-((dungeon_turn/50000L-hoge/10)));
- pls_level = MIN(8,3 + dungeon_turn/400000L-hoge/40);
+ pls_kakuritu = MAX(2, NASTY_MON-((dungeon_turn/(TURNS_PER_TICK*2500L)-hoge/10)));
+ pls_level = MIN(8,3 + dungeon_turn/(TURNS_PER_TICK*20000L)-hoge/40);
}
else
{
if ((level > 0) && !p_ptr->inside_battle && !(d_info[dungeon_type].flags1 & DF1_BEGINNER))
{
/* Nightmare mode allows more out-of depth monsters */
- if (ironman_nightmare && !rand_int(pls_kakuritu))
+ if (ironman_nightmare && !randint0(pls_kakuritu))
{
/* What a bizarre calculation */
- level = 1 + (level * MAX_DEPTH / randint(MAX_DEPTH));
+ level = 1 + (level * MAX_DEPTH / randint1(MAX_DEPTH));
}
else
{
/* Occasional "nasty" monster */
- if (!rand_int(pls_kakuritu))
+ if (!randint0(pls_kakuritu))
{
/* Pick a level bonus */
int d = MIN(5, level/10) + pls_level;
}
/* Occasional "nasty" monster */
- if (!rand_int(pls_kakuritu))
+ if (!randint0(pls_kakuritu))
{
/* Pick a level bonus */
int d = MIN(5, level/10) + pls_level;
if (!p_ptr->inside_battle && !chameleon_change)
{
/* Hack -- "unique" monsters must be "unique" */
- if (((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags7 & (RF7_UNIQUE_7))) &&
+ if (((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ (r_ptr->flags7 & (RF7_UNIQUE_7))) &&
(r_ptr->cur_num >= r_ptr->max_num))
{
continue;
}
- if (r_ptr->flags7 & (RF7_UNIQUE2))
- {
- int j;
- bool fail = FALSE;
- for (j = m_max -1; j >=1; j--)
- {
- if(m_list[j].r_idx == r_idx)
- {
- fail = TRUE;
- break;
- }
- }
- if (fail) continue;
- }
-
- if (r_idx == MON_BANORLUPART)
- {
- int j;
- bool fail = FALSE;
- for (j = m_max -1; j >=1; j--)
- {
- if((m_list[j].r_idx == MON_BANOR) ||(m_list[j].r_idx == MON_LUPART))
- {
- fail = TRUE;
- break;
- }
- }
- if (fail) continue;
- }
-
- /* Hack -- don't create questors */
- if (r_ptr->flags1 & RF1_QUESTOR)
- {
- continue;
- }
-
- if (r_ptr->flags7 & RF7_GUARDIAN)
+ if ((r_ptr->flags7 & (RF7_UNIQUE2)) &&
+ (r_ptr->cur_num >= 1))
{
continue;
}
- /* Depth Monsters never appear out of depth */
- if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (r_ptr->level > dun_level))
+ if (r_idx == MON_BANORLUPART)
{
- continue;
+ if (r_info[MON_BANOR].cur_num > 0) continue;
+ if (r_info[MON_LUPART].cur_num > 0) continue;
}
-
- /* Some dungeon types restrict the possible monsters */
-/* if(!restrict_monster_to_dungeon(r_ptr) && dun_level) continue; */
}
/* Accept */
/* Pick a monster */
- value = rand_int(total);
+ value = randint0(total);
/* Find the monster */
for (i = 0; i < alloc_race_size; i++)
/* Power boost */
- p = rand_int(100);
+ p = randint0(100);
/* Try for a "harder" monster once (50%) or twice (10%) */
if (p < 60)
j = i;
/* Pick a monster */
- value = rand_int(total);
+ value = randint0(total);
/* Find the monster */
for (i = 0; i < alloc_race_size; i++)
j = i;
/* Pick a monster */
- value = rand_int(total);
+ value = randint0(total);
/* Find the monster */
for (i = 0; i < alloc_race_size; i++)
* 0x20 --> Pronominalize visible monsters
* 0x40 --> Assume the monster is hidden
* 0x80 --> Assume the monster is visible
+ * 0x100 --> Chameleon's true name
+ * 0x200 --> Ignore hallucination, and penetrate shape change
*
* Useful Modes:
* 0x00 --> Full nominative name ("the kobold") or "it"
bool seen, pron;
bool named = FALSE;
- if (m_ptr->mflag2 & MFLAG_KAGE) r_ptr = &r_info[MON_KAGE];
- else r_ptr = &r_info[m_ptr->r_idx];
+ r_ptr = &r_info[m_ptr->ap_r_idx];
if ((mode & 0x100) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
{
else name = (r_name + r_ptr->name);
/* Are we hallucinating? (Idea from Nethack...) */
- if (p_ptr->image)
+ if (p_ptr->image && !(mode & 0x200))
{
- if (randint(2) == 1)
+ if (one_in_(2))
{
#ifdef JP
if (!get_rnd_line("silly_j.txt", m_ptr->r_idx, silly_name))
do
{
- hallu_race = &r_info[randint(max_r_idx - 1)];
+ hallu_race = &r_info[randint1(max_r_idx - 1)];
}
while (hallu_race->flags1 & RF1_UNIQUE);
/* Handle all other visible monster requests */
else
{
+ /* Tanuki? */
+ if (is_pet(m_ptr) && m_ptr->ap_r_idx != m_ptr->r_idx)
+ {
+#ifdef JP
+ char *t;
+ strcpy(buf, name);
+ t = buf;
+ while(strncmp(t, "¡Ù", 2) && *t) t++;
+ if (*t)
+ {
+ *t = '\0';
+ (void)sprintf(desc, "%s¡©¡Ù", buf);
+ }
+ else
+ (void)sprintf(desc, "%s¡©", name);
+#else
+ (void)sprintf(desc, "%s?", name);
+#endif
+ }
+ else
+
/* It could be a Unique */
- if ((r_ptr->flags1 & RF1_UNIQUE) && !p_ptr->image)
+ if ((r_ptr->flags1 & RF1_UNIQUE) && !(p_ptr->image && !(mode & 0x200)))
{
/* Start with the name (thus nominative and objective) */
if ((m_ptr->mflag2 & MFLAG_CHAMELEON) && !(mode & 0x100))
#endif
(void)strcat(desc, name);
-
- if (m_ptr->nickname)
- {
-#ifdef JP
- sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
-#else
- sprintf(buf," called %s",quark_str(m_ptr->nickname));
-#endif
- strcat(desc,buf);
- }
}
/* It could be a normal, definite, monster */
#endif
(void)strcat(desc, name);
+ }
- if (m_ptr->nickname)
- {
+ if (m_ptr->nickname)
+ {
#ifdef JP
- sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
+ sprintf(buf,"¡Ö%s¡×",quark_str(m_ptr->nickname));
#else
- sprintf(buf," called %s",quark_str(m_ptr->nickname));
+ sprintf(buf," called %s",quark_str(m_ptr->nickname));
#endif
- strcat(desc,buf);
- }
+ strcat(desc,buf);
+ }
- if ((m_ptr->fy == py) && (m_ptr->fx == px))
+ if ((m_ptr->fy == py) && (m_ptr->fx == px))
+ {
#ifdef JP
- strcat(desc,"(¾èÇÏÃæ)");
+ strcat(desc,"(¾èÇÏÃæ)");
#else
- strcat(desc,"(riding)");
+ strcat(desc,"(riding)");
#endif
- if ((mode & 0x200) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
+ }
+
+ if ((mode & 0x200) && (m_ptr->mflag2 & MFLAG_CHAMELEON))
+ {
+ if (r_ptr->flags1 & RF1_UNIQUE)
{
- if (r_ptr->flags1 & RF1_UNIQUE)
#ifdef JP
- strcat(desc,"(¥«¥á¥ì¥ª¥ó¤Î²¦)");
+ strcat(desc,"(¥«¥á¥ì¥ª¥ó¤Î²¦)");
#else
- strcat(desc,"(Chameleon Lord)");
+ strcat(desc,"(Chameleon Lord)");
#endif
- else
+ }
+ else
+ {
#ifdef JP
- strcat(desc,"(¥«¥á¥ì¥ª¥ó)");
+ strcat(desc,"(¥«¥á¥ì¥ª¥ó)");
#else
- strcat(desc,"(Chameleon)");
+ strcat(desc,"(Chameleon)");
#endif
}
}
+ if ((mode & 0x200) && m_ptr->ap_r_idx != m_ptr->r_idx)
+ {
+ strcat(desc, format("(%s)", r_name + r_info[m_ptr->r_idx].name));
+ }
+
/* Handle the Possessive as a special afterthought */
if (mode & 0x02)
{
/* XXX Check for trailing "s" */
-
+
/* Simply append "apostrophe" and "s" */
#ifdef JP
(void)strcat(desc, "¤Î");
if (is_pet(m_ptr))
return; /* Pet eldritch horrors are safe most of the time */
- if (randint(100) > power) return;
+ if (randint1(100) > power) return;
if (saving_throw(p_ptr->skill_sav - power))
{
msg_format("You behold the %s visage of %s!",
#endif
- funny_desc[rand_int(MAX_SAN_FUNNY)], m_name);
+ funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
- if (randint(3) == 1)
+ if (one_in_(3))
{
- msg_print(funny_comments[rand_int(MAX_SAN_COMMENT)]);
- p_ptr->image = p_ptr->image + randint(r_ptr->level);
+ msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
+ p_ptr->image = p_ptr->image + randint1(r_ptr->level);
}
return; /* Never mind; we can't see it clearly enough */
msg_format("You behold the %s visage of %s!",
#endif
- horror_desc[rand_int(MAX_SAN_HORROR)], m_name);
+ horror_desc[randint0(MAX_SAN_HORROR)], m_name);
r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
{
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ (void)set_confused(p_ptr->confused + randint0(4) + 4);
}
if (!p_ptr->resist_chaos && one_in_(3))
{
- (void)set_image(p_ptr->image + rand_int(250) + 150);
+ (void)set_image(p_ptr->image + randint0(250) + 150);
}
return;
}
{
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ (void)set_confused(p_ptr->confused + randint0(4) + 4);
}
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ (void)set_paralyzed(p_ptr->paralyzed + randint0(4) + 4);
}
- while (rand_int(100) > p_ptr->skill_sav)
+ while (randint0(100) > p_ptr->skill_sav)
(void)do_dec_stat(A_INT);
- while (rand_int(100) > p_ptr->skill_sav)
+ while (randint0(100) > p_ptr->skill_sav)
(void)do_dec_stat(A_WIS);
if (!p_ptr->resist_chaos)
{
- (void)set_image(p_ptr->image + rand_int(250) + 150);
+ (void)set_image(p_ptr->image + randint0(250) + 150);
}
return;
}
while (!happened)
{
- switch (randint(21))
+ switch (randint1(21))
{
case 1:
if (!(p_ptr->muta3 & MUT3_MORONIC) && one_in_(5))
if (p_ptr->riding == m_idx) p_ptr->redraw |= (PR_UHEALTH);
/* Hack -- Count "fresh" sightings */
- if ((m_ptr->mflag2 & MFLAG_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
+ if ((m_ptr->ap_r_idx == MON_KAGE) && (r_info[MON_KAGE].r_sights < MAX_SHORT))
r_info[MON_KAGE].r_sights++;
- else if (r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++;
+ else if (m_ptr->ap_r_idx == m_ptr->r_idx &&
+ r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++;
/* Eldritch Horror */
if (r_ptr->flags2 & RF2_ELDRITCH_HORROR)
}
+static bool monster_hook_chameleon_lord(int r_idx)
+{
+ monster_race *r_ptr = &r_info[r_idx];
+
+ if (!(r_ptr->flags1 & (RF1_UNIQUE))) return FALSE;
+ if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON)) return FALSE;
+
+ if (ABS(r_ptr->level - r_info[MON_CHAMELEON_K].level) > 5) return FALSE;
+
+ if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE))
+ return FALSE;
+
+ return TRUE;
+}
+
+static bool monster_hook_chameleon(int r_idx)
+{
+ monster_race *r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags1 & (RF1_UNIQUE)) return FALSE;
+ if (r_ptr->flags2 & RF2_MULTIPLY) return FALSE;
+ if (r_ptr->flags7 & (RF7_FRIENDLY | RF7_CHAMELEON)) return FALSE;
+
+ if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE))
+ return FALSE;
+
+ return (*(get_monster_hook()))(r_idx);
+}
+
void choose_new_monster(int m_idx, bool born, int r_idx)
{
int old_r_idx = m_ptr->r_idx;
bool old_unique = FALSE;
- if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) old_unique = TRUE;
+ if (r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE)
+ old_unique = TRUE;
if (old_unique && (r_idx == MON_CHAMELEON)) r_idx = MON_CHAMELEON_K;
r_ptr = &r_info[r_idx];
if (!r_idx)
{
chameleon_change = TRUE;
- get_mon_num_prep(get_monster_hook(), NULL);
+ if (old_unique)
+ get_mon_num_prep(monster_hook_chameleon_lord, NULL);
+ else
+ get_mon_num_prep(monster_hook_chameleon, NULL);
+
while (attempt--)
{
int level;
- if (!dun_level) level = wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].level;
- else level = dun_level;
- if (d_info[dungeon_type].flags1 & DF1_CHAMELEON) level+= 2+randint(3);
+ if (old_unique)
+ level = r_info[MON_CHAMELEON_K].level;
+ else if (!dun_level)
+ level = wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].level;
+ else
+ level = dun_level;
+
+ if (d_info[dungeon_type].flags1 & DF1_CHAMELEON) level+= 2+randint1(3);
r_idx = get_mon_num(level);
r_ptr = &r_info[r_idx];
- if ((old_unique && !(r_ptr->flags1 & RF1_UNIQUE)) || (!old_unique && (r_ptr->flags1 & RF1_UNIQUE))) continue;
- if (old_unique)
- {
- if (ABS(r_ptr->level - r_info[MON_CHAMELEON_K].level) > 5) continue;
- if ((r_ptr->blow[0].method == RBM_EXPLODE) || (r_ptr->blow[1].method == RBM_EXPLODE) || (r_ptr->blow[2].method == RBM_EXPLODE) || (r_ptr->blow[3].method == RBM_EXPLODE)) continue;
- }
- if ((r_ptr->flags2 & RF2_MULTIPLY) || (r_ptr->flags7 & (RF7_UNIQUE_7 | RF7_GUARDIAN | RF7_FRIENDLY | RF7_UNIQUE2 | RF7_CHAMELEON))) continue;
+
if (!monster_can_cross_terrain(cave[m_ptr->fy][m_ptr->fx].feat, r_ptr)) continue;
if (!born && !old_unique)
{
if ((r_info[old_r_idx].flags3 & RF3_EVIL) && !(r_ptr->flags3 & RF3_EVIL)) continue;
if (!(r_info[old_r_idx].flags3 & (RF3_GOOD | RF3_EVIL)) && (r_ptr->flags3 & (RF3_GOOD | RF3_EVIL))) continue;
}
- if (born && !old_unique && summon_specific_type)
- {
- if (!summon_specific_aux(r_idx)) continue;
- }
break;
}
chameleon_change = FALSE;
}
m_ptr->r_idx = r_idx;
+ m_ptr->ap_r_idx = r_idx;
update_mon(m_idx, FALSE);
lite_spot(m_ptr->fy, m_ptr->fx);
if (born) return;
m_ptr->mspeed = r_ptr->speed;
/* Hack -- small racial variety */
/* Allow some small variation per monster */
- if(rand_int(4) == 1){
+ if(one_in_(4)){
i = extract_energy[r_ptr->speed] / 3;
if (i) m_ptr->mspeed += rand_spread(0, i);
}
m_ptr->hp = (long)(m_ptr->hp * m_ptr->max_maxhp) / oldmaxhp;
}
+/*
+ * Set initial racial appearance of a monster
+ */
+static int initial_r_appearance(int r_idx)
+{
+ int ap_r_idx;
+ int min = MIN(base_level-5, 50);
+
+ if (!(r_info[r_idx].flags7 & RF7_TANUKI))
+ return r_idx;
+
+ get_mon_num_prep(monster_hook_chameleon, NULL);
+
+ while (1)
+ {
+ ap_r_idx = get_mon_num(base_level + 10);
+ if (r_info[ap_r_idx].flags7 & RF7_AQUATIC) continue;
+ if (r_info[ap_r_idx].level >= min) break;
+ }
+ return ap_r_idx;
+}
+
/*
* Attempt to place a monster of the given race at the given location.
* This is the only function which may place a monster in the dungeon,
* except for the savefile loading code.
*/
-bool place_monster_one(int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
+bool place_monster_one(int who, int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
{
int i;
int rune_dam = 0;
if (!p_ptr->inside_battle)
{
- /* Hack -- "unique" monsters must be "unique" */
- if (((r_ptr->flags1 & (RF1_UNIQUE)) || (r_ptr->flags7 & (RF7_UNIQUE_7))) &&
- (r_ptr->cur_num >= r_ptr->max_num))
- {
- /* Cannot create */
- return (FALSE);
- }
-
- if (r_ptr->flags7 & (RF7_UNIQUE2))
- {
- int j;
- bool fail = FALSE;
- for (j = m_max -1; j >=1; j--)
+ /* Hack -- "unique" monsters must be "unique" */
+ if (((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ (r_ptr->flags7 & (RF7_UNIQUE_7))) &&
+ (r_ptr->cur_num >= r_ptr->max_num))
{
- if(m_list[j].r_idx == r_idx)
- {
- fail = TRUE;
- break;
- }
+ /* Cannot create */
+ return (FALSE);
}
- if (fail) return (FALSE);
- }
-
- if (r_idx == MON_BANORLUPART)
- {
- int j;
- bool fail = FALSE;
- for (j = m_max -1; j >=1; j--)
+
+ if ((r_ptr->flags7 & (RF7_UNIQUE2)) &&
+ (r_ptr->cur_num >= 1))
{
- if((m_list[j].r_idx == MON_BANOR) ||(m_list[j].r_idx == MON_LUPART))
- {
- fail = TRUE;
- break;
- }
+ return (FALSE);
}
- if (fail) return (FALSE);
- }
- /* Depth monsters may NOT be created out of depth, unless in Nightmare mode */
- if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (dun_level < r_ptr->level) &&
- (!ironman_nightmare || (r_ptr->flags1 & (RF1_QUESTOR))))
- {
- /* Cannot create */
- return (FALSE);
- }
+ if (r_idx == MON_BANORLUPART)
+ {
+ if (r_info[MON_BANOR].cur_num > 0) return FALSE;
+ if (r_info[MON_LUPART].cur_num > 0) return FALSE;
+ }
+
+ /* Depth monsters may NOT be created out of depth, unless in Nightmare mode */
+ if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (dun_level < r_ptr->level) &&
+ (!ironman_nightmare || (r_ptr->flags1 & (RF1_QUESTOR))))
+ {
+ /* Cannot create */
+ return (FALSE);
+ }
}
if(quest_number(dun_level))
if (c_ptr->feat == FEAT_GLYPH)
{
- if (randint(BREAK_GLYPH) < (r_ptr->level+20))
+ if (randint1(BREAK_GLYPH) < (r_ptr->level+20))
{
/* Describe observable breakage */
if (c_ptr->info & CAVE_MARK)
c_ptr->info &= ~(CAVE_MARK);
/* Break the rune */
- c_ptr->feat = floor_type[rand_int(100)];
- c_ptr->info &= ~(CAVE_MASK);
- c_ptr->info |= CAVE_FLOOR;
+ c_ptr->feat = floor_type[randint0(100)];
/* Notice */
note_spot(y, x);
/* Save the race */
m_ptr->r_idx = r_idx;
+ m_ptr->ap_r_idx = initial_r_appearance(r_idx);
+
+ /* Sub-alignment of a monster */
+ if ((who > 0) && !(r_ptr->flags3 & (RF3_EVIL | RF3_GOOD)))
+ m_ptr->sub_align = m_list[who].sub_align;
+ else
+ {
+ m_ptr->sub_align = SUB_ALIGN_NEUTRAL;
+ if (r_ptr->flags3 & RF3_EVIL) m_ptr->sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) m_ptr->sub_align |= SUB_ALIGN_GOOD;
+ }
/* Place the monster at the location */
m_ptr->fy = y;
/* Unknown distance */
m_ptr->cdis = 0;
- m_ptr->target_y = 0;
- m_ptr->target_x = 0;
+ reset_target(m_ptr);
m_ptr->nickname = 0;
m_ptr->mflag2 |= MFLAG_CHAMELEON;
rating++;
}
- else if (is_kage) m_ptr->mflag2 |= MFLAG_KAGE;
+ else if (is_kage)
+ {
+ m_ptr->ap_r_idx = MON_KAGE;
+ m_ptr->mflag2 |= MFLAG_KAGE;
+ }
+
if (no_pet) m_ptr->mflag2 |= MFLAG_NOPET;
/* Not visible */
if (slp && r_ptr->sleep && !ironman_nightmare)
{
int val = r_ptr->sleep;
- m_ptr->csleep = ((val * 2) + randint(val * 10));
+ m_ptr->csleep = ((val * 2) + randint1(val * 10));
}
/* Assign maximal hitpoints */
if (!(r_ptr->flags1 & RF1_UNIQUE) && !p_ptr->inside_arena)
{
/* Allow some small variation per monster */
- if(rand_int(4) == 1){
+ if(one_in_(4)){
i = extract_energy[r_ptr->speed] / 3;
if (i) m_ptr->mspeed += rand_spread(0, i);
}
}
}
+ if (summon_specific_type == SUMMON_KNIGHTS) m_ptr->fast = 100;
+
if (m_ptr->mspeed > 199) m_ptr->mspeed = 199;
/* Give a random starting energy */
- m_ptr->energy = (byte)rand_int(100);
-
- /* Nightmare monsters are more prepared */
- if (ironman_nightmare)
+ if (!ironman_nightmare)
{
- m_ptr->energy *= 2;
+ m_ptr->energy_need = ENERGY_NEED() - (s16b)randint0(100);
+ }
+ else
+ {
+ /* Nightmare monsters are more prepared */
+ m_ptr->energy_need = ENERGY_NEED() - (s16b)randint0(100) * 2;
}
/* Force monster to wait for player, unless in Nightmare mode */
/* Hack -- Count the monsters on the level */
- r_ptr->cur_num++;
+ if (m_ptr->mflag2 & MFLAG_CHAMELEON)
+ r_info[r_idx].cur_num++;
+ else
+ r_ptr->cur_num++;
/* Hack -- Count the number of "reproducers" */
if (p_ptr->warning && character_dungeon)
{
- cptr color;
if (r_ptr->flags1 & RF1_UNIQUE)
{
+ cptr color;
+ object_type *o_ptr;
+ char o_name[MAX_NLEN];
+
if (r_ptr->level > p_ptr->lev + 30)
#ifdef JP
color = "¹õ¤¯";
#else
color = "white";
#endif
+
+ o_ptr = choose_warning_item();
+ object_desc(o_name, o_ptr, FALSE, 0);
#ifdef JP
- msg_format("»ØÎؤÏ%s¸÷¤Ã¤¿¡£",color);
+ msg_format("%s¤Ï%s¸÷¤Ã¤¿¡£",o_name, color);
#else
- msg_format("Your ring glows %s.",color);
+ msg_format("%s glows %s.",o_name, color);
#endif
}
}
if (c_ptr->feat == FEAT_MINOR_GLYPH)
{
/* Break the ward */
- if (randint(BREAK_MINOR_GLYPH) > r_ptr->level)
+ if (randint1(BREAK_MINOR_GLYPH) > r_ptr->level)
{
/* Describe observable breakage */
if (c_ptr->info & CAVE_MARK)
c_ptr->info &= ~(CAVE_MARK);
/* Break the rune */
- c_ptr->feat = floor_type[rand_int(100)];
- c_ptr->info &= ~(CAVE_MASK);
- c_ptr->info |= CAVE_FLOOR;
+ c_ptr->feat = floor_type[randint0(100)];
note_spot(y, x);
lite_spot(y, x);
}
/*
* Attempt to place a "group" of monsters around the given location
*/
-static bool place_monster_group(int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
+static bool place_monster_group(int who, int y, int x, int r_idx, bool slp, bool friendly, bool pet, bool no_pet)
{
monster_race *r_ptr = &r_info[r_idx];
/* Pick a group size */
- total = randint(10);
+ total = randint1(10);
/* Hard monsters, small groups */
if (r_ptr->level > dun_level)
{
extra = r_ptr->level - dun_level;
- extra = 0 - randint(extra);
+ extra = 0 - randint1(extra);
}
/* Easy monsters, large groups */
else if (r_ptr->level < dun_level)
{
extra = dun_level - r_ptr->level;
- extra = randint(extra);
+ extra = randint1(extra);
}
/* Hack -- limit group reduction */
if (!cave_empty_bold2(my, mx)) continue;
/* Attempt to place another monster */
- if (place_monster_one(my, mx, r_idx, slp, friendly, pet, no_pet))
+ if (place_monster_one(who, my, mx, r_idx, slp, friendly, pet, no_pet))
{
/* Add it to the "hack" set */
hack_y[hack_n] = my;
* Hack -- help pick an escort type
*/
static int place_monster_idx = 0;
+static int place_monster_m_idx = 0;
/*
* Hack -- help pick an escort type
static bool place_monster_okay(int r_idx)
{
monster_race *r_ptr = &r_info[place_monster_idx];
+ monster_type *m_ptr = &m_list[place_monster_m_idx];
monster_race *z_ptr = &r_info[r_idx];
/* Paranoia -- Skip identical monsters */
if (place_monster_idx == r_idx) return (FALSE);
+ /* Skip different alignment */
+ if (((m_ptr->sub_align & SUB_ALIGN_EVIL) && (z_ptr->flags3 & RF3_GOOD)) ||
+ ((m_ptr->sub_align & SUB_ALIGN_GOOD) && (z_ptr->flags3 & RF3_EVIL)))
+ return FALSE;
+
+ if (r_ptr->flags7 & RF7_FRIENDLY)
+ {
+ if (((p_ptr->align < 0) && (z_ptr->flags3 & RF3_GOOD)) ||
+ ((p_ptr->align > 0) && (z_ptr->flags3 & RF3_EVIL)))
+ return FALSE;
+ }
+
+ if ((r_ptr->flags7 & RF7_CHAMELEON) && !(z_ptr->flags7 & RF7_CHAMELEON))
+ return FALSE;
+
/* Okay */
return (TRUE);
}
* Note the use of the new "monster allocation table" code to restrict
* the "get_mon_num()" function to "legal" escort types.
*/
-bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, bool friendly, bool pet, bool no_kage, bool no_pet)
+bool place_monster_aux(int who, int y, int x, int r_idx, bool slp, bool grp, bool friendly, bool pet, bool no_kage, bool no_pet)
{
int i;
monster_race *r_ptr = &r_info[r_idx];
else is_kage = FALSE;
/* Place one monster, or fail */
- if (!place_monster_one(y, x, r_idx, slp, friendly, pet, no_pet)) return (FALSE);
+ if (!place_monster_one(who, y, x, r_idx, slp, friendly, pet, no_pet)) return (FALSE);
/* Require the "group" flag */
if (!grp) return (TRUE);
+ place_monster_m_idx = hack_m_idx_ii;
/* Friends for certain monsters */
if (r_ptr->flags1 & (RF1_FRIENDS))
{
/* Attempt to place a group */
- (void)place_monster_group(y, x, r_idx, slp, friendly, pet, no_pet);
+ (void)place_monster_group(who, y, x, r_idx, slp, friendly, pet, no_pet);
}
/* Handle failure */
if (!z) break;
- if (((r_ptr->flags3 & RF3_EVIL) && (r_info[z].flags3 & RF3_GOOD)) || ((r_ptr->flags3 & RF3_GOOD) && (r_info[z].flags3 & RF3_EVIL)))
- {
- i--;
- continue;
- }
-
- if (r_ptr->flags7 & RF7_FRIENDLY)
- {
- if (((p_ptr->align < 0) && (r_info[z].flags3 & RF3_GOOD)) ||
- ((p_ptr->align > 0) && (r_info[z].flags3 & RF3_EVIL)))
- {
- i--;
- continue;
- }
- }
-
/* Place a single escort */
- (void)place_monster_one(ny, nx, z, slp, friendly, pet, no_pet);
+ (void)place_monster_one(place_monster_m_idx, ny, nx, z, slp, friendly, pet, no_pet);
/* Place a "group" of escorts if needed */
if ((r_info[z].flags1 & RF1_FRIENDS) ||
(r_ptr->flags1 & RF1_ESCORTS))
{
/* Place a group of monsters */
- (void)place_monster_group(ny, nx, z, slp, friendly, pet, no_pet);
+ (void)place_monster_group(place_monster_m_idx, ny, nx, z, slp, friendly, pet, no_pet);
}
}
}
if (!r_idx) return (FALSE);
/* Attempt to place the monster */
- if (place_monster_aux(y, x, r_idx, slp, grp, FALSE, FALSE, FALSE, FALSE)) return (TRUE);
+ if (place_monster_aux(0, y, x, r_idx, slp, grp, FALSE, FALSE, FALSE, FALSE)) return (TRUE);
/* Oops */
return (FALSE);
while (--attempts)
{
/* Attempt to place the monster */
- if (place_monster_aux(y, x, r_idx, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)) break;
+ if (place_monster_aux(0, y, x, r_idx, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)) break;
}
if (attempts < 1) {horde_align = 0;return FALSE;}
if (m_list[m_idx].mflag2 & MFLAG_CHAMELEON) r_ptr = &r_info[m_list[m_idx].r_idx];
summon_kin_type = r_ptr->d_char;
- for (attempts = randint(10) + 5; attempts; attempts--)
+ for (attempts = randint1(10) + 5; attempts; attempts--)
{
scatter(&cy, &cx, y, x, 5, 0);
{
int y = 0, x = 0;
int attempts_left = 10000;
+ int guardian = d_info[dungeon_type].final_guardian;
+
+ /* Put an Guardian */
+ if(guardian && d_info[dungeon_type].maxdepth == dun_level && r_info[guardian].cur_num < r_info[guardian].max_num )
+ {
+ int oy;
+ int ox;
+ int try = 4000;
+
+ /* Find a good position */
+ while(try)
+ {
+ /* Get a random spot */
+ oy = randint1(cur_hgt - 4) + 2;
+ ox = randint1(cur_wid - 4) + 2;
+
+ /* Is it a good spot ? */
+ if (cave_empty_bold2(oy, ox) && monster_can_cross_terrain(cave[oy][ox].feat, &r_info[guardian]))
+ {
+ /* Place the guardian */
+ if (place_monster_aux(0, oy, ox, guardian, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE)) break;
+ }
+ /* One less try */
+ try--;
+ }
+ }
+
/* Find a legal, distant, unoccupied, space */
while (attempts_left--)
{
/* Pick a location */
- y = rand_int(cur_hgt);
- x = rand_int(cur_wid);
+ y = randint0(cur_hgt);
+ x = randint0(cur_wid);
/* Require empty floor grid (was "naked") */
if (dun_level || (wilderness[p_ptr->wilderness_y][p_ptr->wilderness_x].terrain != TERRAIN_MOUNTAIN))
#ifdef MONSTER_HORDES
- if (randint(5000) <= dun_level)
+ if (randint1(5000) <= dun_level)
{
if (alloc_horde(y, x))
{
if (summon_specific_who > 0)
{
monster_type *m_ptr = &m_list[summon_specific_who];
- monster_race *s_ptr = &r_info[m_ptr->r_idx];
/* Do not summon enemies */
/* Friendly vs. opposite aligned normal or pet */
if (((r_ptr->flags3 & RF3_EVIL) &&
- (s_ptr->flags3 & RF3_GOOD)) ||
+ (m_ptr->sub_align & SUB_ALIGN_GOOD)) ||
((r_ptr->flags3 & RF3_GOOD) &&
- (s_ptr->flags3 & RF3_EVIL)))
+ (m_ptr->sub_align & SUB_ALIGN_EVIL)))
{
return FALSE;
}
/* Do not summon enemies of the pets */
if ((p_ptr->align < -9) && (r_ptr->flags3 & RF3_GOOD))
{
- if (!(one_in_((0-p_ptr->align)/2+1))) return FALSE;
+ if (!one_in_((0-p_ptr->align)/2+1)) return FALSE;
}
else if ((p_ptr->align > 9) && (r_ptr->flags3 & RF3_EVIL))
{
- if (!(one_in_(p_ptr->align/2+1))) return FALSE;
+ if (!one_in_(p_ptr->align/2+1)) return FALSE;
}
}
if ((type == SUMMON_BLUE_HORROR) || (type == SUMMON_DAWN)) no_kage = TRUE;
/* Attempt to place the monster (awake, allow groups) */
- if (!place_monster_aux(y, x, r_idx, FALSE, group, friendly, pet, no_kage, no_pet))
+ if (!place_monster_aux(who, y, x, r_idx, FALSE, group, friendly, pet, no_kage, no_pet))
{
summon_specific_type = 0;
return (FALSE);
}
/* A "dangerous" function, creates a pet of the specified type */
-bool summon_named_creature (int oy, int ox, int r_idx, bool slp, bool group_ok, bool friendly, bool pet)
+bool summon_named_creature (int who, int oy, int ox, int r_idx, bool slp, bool group_ok, bool friendly, bool pet)
{
int x, y;
if (!mon_scatter(&y, &x, oy, ox, 2)) return FALSE;
/* Place it (allow groups) */
- return place_monster_aux(y, x, r_idx, slp, group_ok, friendly, pet, TRUE, FALSE);
+ return place_monster_aux(who, y, x, r_idx, slp, group_ok, friendly, pet, TRUE, FALSE);
}
return FALSE;
/* Create a new monster (awake, no groups) */
- if (!place_monster_aux(y, x, m_ptr->r_idx, FALSE, FALSE, friendly, pet, TRUE, (bool)(m_ptr->mflag2 & MFLAG_NOPET)))
+ if (!place_monster_aux(m_idx, y, x, m_ptr->r_idx, FALSE, FALSE, friendly, pet, TRUE, (bool)(m_ptr->mflag2 & MFLAG_NOPET)))
return FALSE;
if (clone)
if (r_ptr->flags2 & (RF2_STUPID)) return;
/* Not intelligent, only learn sometimes */
- if (!(r_ptr->flags2 & (RF2_SMART)) && (rand_int(100) < 50)) return;
+ if (!(r_ptr->flags2 & (RF2_SMART)) && (randint0(100) < 50)) return;
/* XXX XXX XXX */