この過程で, 以下の修正や変更を含む.
* モンスター魔法 "死者復活" の使用判定で, 敵対属性の死体しか周囲にな
い場合は死者復活を使用しないようにした. また, この判定はモンスター
対モンスターにも適用される.
* 善良かつ邪悪のモンスターが別の善良かつ邪悪のモンスターを召喚できな
かったバグを修正.
extern bool monster_can_cross_terrain(byte feat, monster_race *r_ptr);
extern bool monster_can_enter(int y, int x, monster_race *r_ptr);
extern bool are_enemies(monster_type *m_ptr1, monster_type *m_ptr2);
+extern bool monster_has_hostile_align(monster_type *m_ptr, int pa_good, int pa_evil, monster_race *r_ptr);
extern bool monster_living(monster_race *r_ptr);
extern bool no_questor_or_bounty_uniques(int r_idx);
/* mspells1.c */
extern bool clean_shot(int y1, int x1, int y2, int x2, bool friend);
extern bool summon_possible(int y1, int x1);
+extern bool raise_possible(monster_type *m_ptr);
extern bool spell_is_inate(u16b spell);
/* mspells2.c */
/* Paranoia... no pet uniques outside wizard mode -- TY */
if (is_pet(m_ptr) &&
((((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_UNIQUE_7)) &&
- ((p_ptr->align > 9 && (r_ptr->flags3 & RF3_EVIL)) ||
- (p_ptr->align < -9 && (r_ptr->flags3 & RF3_GOOD))))
+ monster_has_hostile_align(NULL, 10, -10, r_ptr))
|| (r_ptr->flagsr & RFR_RES_ALL)))
{
gets_angry = TRUE;
}
+/*
+ * Check if this monster has "hostile" alignment (aux)
+ */
+static bool check_hostile_align(byte sub_align1, byte sub_align2)
+{
+ if (sub_align1 != sub_align2)
+ {
+ if (((sub_align1 & SUB_ALIGN_EVIL) && (sub_align2 & SUB_ALIGN_GOOD)) ||
+ ((sub_align1 & SUB_ALIGN_GOOD) && (sub_align2 & SUB_ALIGN_EVIL)))
+ return TRUE;
+ }
+
+ /* Non-hostile alignment */
+ return FALSE;
+}
+
/*
* Check if two monsters are enemies
}
/* Friendly vs. opposite aligned normal or pet */
- if (m_ptr->sub_align != n_ptr->sub_align)
+ if (check_hostile_align(m_ptr->sub_align, n_ptr->sub_align))
{
- if (((m_ptr->sub_align & SUB_ALIGN_EVIL) &&
- (n_ptr->sub_align & SUB_ALIGN_GOOD)) ||
- ((m_ptr->sub_align & SUB_ALIGN_GOOD) &&
- (n_ptr->sub_align & SUB_ALIGN_EVIL)))
- {
- if (!(m_ptr->mflag2 & MFLAG2_CHAMELEON) || !(n_ptr->mflag2 & MFLAG2_CHAMELEON)) return TRUE;
- }
+ if (!(m_ptr->mflag2 & MFLAG2_CHAMELEON) || !(n_ptr->mflag2 & MFLAG2_CHAMELEON)) return TRUE;
}
/* Hostile vs. non-hostile */
/*
+ * Check if this monster race has "hostile" alignment
+ * If user is player, m_ptr == NULL.
+ */
+bool monster_has_hostile_align(monster_type *m_ptr, int pa_good, int pa_evil, monster_race *r_ptr)
+{
+ byte sub_align1 = SUB_ALIGN_NEUTRAL;
+ byte sub_align2 = SUB_ALIGN_NEUTRAL;
+
+ if (m_ptr) /* For a monster */
+ {
+ sub_align1 = m_ptr->sub_align;
+ }
+ else /* For player */
+ {
+ if (p_ptr->align >= pa_good) sub_align1 |= SUB_ALIGN_GOOD;
+ if (p_ptr->align <= pa_evil) sub_align1 |= SUB_ALIGN_EVIL;
+ }
+
+ /* Racial alignment flags */
+ if (r_ptr->flags3 & RF3_EVIL) sub_align2 |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) sub_align2 |= SUB_ALIGN_GOOD;
+
+ if (check_hostile_align(sub_align1, sub_align2)) return TRUE;
+
+ /* Non-hostile alignment */
+ return FALSE;
+}
+
+
+/*
* Is the monster "alive"?
*
* Used to determine the message to print for a killed monster.
/* Not born */
if (!(old_r_ptr->flags7 & RF7_CHAMELEON))
{
- if ((m_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
- if ((m_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+ if (monster_has_hostile_align(m_ptr, 0, 0, r_ptr)) return FALSE;
}
/* Born now */
else if (summon_specific_who > 0)
{
- monster_type *sm_ptr = &m_list[summon_specific_who];
-
- if ((sm_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
- if ((sm_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+ if (monster_has_hostile_align(&m_list[summon_specific_who], 0, 0, r_ptr)) return FALSE;
}
return TRUE;
/* Born now */
else if (summon_specific_who > 0)
{
- monster_type *sm_ptr = &m_list[summon_specific_who];
-
- if ((sm_ptr->sub_align & SUB_ALIGN_EVIL) && (r_ptr->flags3 & RF3_GOOD)) return FALSE;
- if ((sm_ptr->sub_align & SUB_ALIGN_GOOD) && (r_ptr->flags3 & RF3_EVIL)) return FALSE;
+ if (monster_has_hostile_align(&m_list[summon_specific_who], 0, 0, r_ptr)) return FALSE;
}
return (*(get_monster_hook()))(r_idx);
else if ((r_ptr->flags7 & RF7_FRIENDLY) ||
(mode & PM_FORCE_FRIENDLY) || is_friendly_idx(who))
{
- if (!(p_ptr->align >= 0 && (r_ptr->flags3 & RF3_EVIL)) &&
- !(p_ptr->align < 0 && (r_ptr->flags3 & RF3_GOOD)))
- {
- set_friendly(m_ptr);
- }
+ if (!monster_has_hostile_align(NULL, 0, -1, r_ptr)) set_friendly(m_ptr);
}
/* Assume no sleeping */
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 (monster_has_hostile_align(m_ptr, 0, 0, z_ptr)) 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 (monster_has_hostile_align(NULL, 1, -1, z_ptr)) return FALSE;
}
if ((r_ptr->flags7 & RF7_CHAMELEON) && !(z_ptr->flags7 & RF7_CHAMELEON))
/* Do not summon enemies */
/* Friendly vs. opposite aligned normal or pet */
- if (((r_ptr->flags3 & RF3_EVIL) &&
- (m_ptr->sub_align & SUB_ALIGN_GOOD)) ||
- ((r_ptr->flags3 & RF3_GOOD) &&
- (m_ptr->sub_align & SUB_ALIGN_EVIL)))
- {
- return FALSE;
- }
+ if (monster_has_hostile_align(m_ptr, 0, 0, r_ptr)) return FALSE;
/* Hostile vs. non-hostile */
- if (is_hostile(m_ptr) != summon_specific_hostile)
- {
- return FALSE;
- }
+ if (is_hostile(m_ptr) != summon_specific_hostile) return FALSE;
}
/* Use the player's alignment */
else if (summon_specific_who < 0)
{
/* 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;
- }
- else if ((p_ptr->align > 9) && (r_ptr->flags3 & RF3_EVIL))
+ if (monster_has_hostile_align(NULL, 10, -10, r_ptr))
{
- if (!one_in_(p_ptr->align/2+1)) return FALSE;
+ if (!one_in_(ABS(p_ptr->align) / 2 + 1)) return FALSE;
}
}
if ((summon_specific_who < 0) &&
((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_UNIQUE_7)) &&
- (((p_ptr->align > 9) && (r_ptr->flags3 & RF3_EVIL)) ||
- ((p_ptr->align < -9) && (r_ptr->flags3 & RF3_GOOD))))
+ monster_has_hostile_align(NULL, 10, -10, r_ptr))
return FALSE;
if ((r_ptr->flags7 & RF7_CHAMELEON) && (d_info[dungeon_type].flags1 & DF1_CHAMELEON)) return TRUE;
}
-static bool raise_possible(int y, int x)
+bool raise_possible(monster_type *m_ptr)
{
int xx, yy;
+ int y = m_ptr->fy;
+ int x = m_ptr->fx;
s16b this_o_idx, next_o_idx = 0;
cave_type *c_ptr;
/* Known to be worthless? */
if (o_ptr->tval == TV_CORPSE)
- return TRUE;
+ {
+ if (!monster_has_hostile_align(m_ptr, 0, 0, &r_info[o_ptr->pval])) return TRUE;
+ }
}
}
}
}
/* Raise-dead if possible (sometimes) */
- if (raise_num && (randint0(100) < 40) && raise_possible(m_ptr->fy, m_ptr->fx))
+ if (raise_num && (randint0(100) < 40))
{
/* Choose raise-dead spell */
return (raise[randint0(raise_num)]);
f6 &= ~(RF6_SUMMON_MASK);
}
+ /* Check for a possible raise dead */
+ if ((f6 & RF6_RAISE_DEAD) && !raise_possible(m_ptr))
+ {
+ /* Remove raise dead spell */
+ f6 &= ~(RF6_RAISE_DEAD);
+ }
+
/* No spells left */
if (!f4 && !f5 && !f6) return (FALSE);
}
f5 &= ~(RF5_SUMMON_MASK);
f6 &= ~(RF6_SUMMON_MASK);
}
+
+ /* Check for a possible raise dead */
+ if ((f6 & RF6_RAISE_DEAD) && !raise_possible(m_ptr))
+ {
+ /* Remove raise dead spell */
+ f6 &= ~(RF6_RAISE_DEAD);
+ }
}
if (r_ptr->flags2 & RF2_SMART)
int i;
nest_mon_info_type nest_mon_info[NUM_NEST_MON_TYPE];
- int align = 0;
+ monster_type align;
cave_type *c_ptr;
/* Prepare allocation table */
get_mon_num_prep(n_ptr->hook_func, NULL);
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
/* Pick some monster types */
for (i = 0; i < NUM_NEST_MON_TYPE; i++)
{
int r_idx = 0, attempts = 100;
+ monster_race *r_ptr = NULL;
while (attempts--)
{
/* Get a (hard) monster type */
r_idx = get_mon_num(dun_level + 10);
+ r_ptr = &r_info[r_idx];
/* Decline incorrect alignment */
- if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
- ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
- {
- continue;
- }
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
/* Accept this monster */
break;
if (!r_idx || !attempts) return;
/* Note the alignment */
- if (r_info[r_idx].flags3 & RF3_GOOD) align++;
- else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
nest_mon_info[i].r_idx = r_idx;
nest_mon_info[i].used = FALSE;
int what[16];
- int align = 0;
+ monster_type align;
cave_type *c_ptr;
/* Prepare allocation table */
get_mon_num_prep(n_ptr->hook_func, NULL);
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
/* Pick some monster types */
for (i = 0; i < 16; i++)
{
int r_idx = 0, attempts = 100;
+ monster_race *r_ptr = NULL;
while (attempts--)
{
/* Get a (hard) monster type */
r_idx = get_mon_num(dun_level + 10);
+ r_ptr = &r_info[r_idx];
/* Decline incorrect alignment */
- if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
- ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
- {
- continue;
- }
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
/* Accept this monster */
break;
if (!r_idx || !attempts) return;
/* Note the alignment */
- if (r_info[r_idx].flags3 & RF3_GOOD) align++;
- else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
what[i] = r_idx;
}
int what[16];
- int align = 0;
+ monster_type align;
cave_type *c_ptr;
/* Prepare allocation table */
get_mon_num_prep(n_ptr->hook_func, vault_aux_trapped_pit);
+ align.sub_align = SUB_ALIGN_NEUTRAL;
+
/* Pick some monster types */
for (i = 0; i < 16; i++)
{
int r_idx = 0, attempts = 100;
+ monster_race *r_ptr = NULL;
while (attempts--)
{
/* Get a (hard) monster type */
r_idx = get_mon_num(dun_level + 0);
+ r_ptr = &r_info[r_idx];
/* Decline incorrect alignment */
- if (((align < 0) && (r_info[r_idx].flags3 & RF3_GOOD)) ||
- ((align > 0) && (r_info[r_idx].flags3 & RF3_EVIL)))
- {
- continue;
- }
+ if (monster_has_hostile_align(&align, 0, 0, r_ptr)) continue;
/* Accept this monster */
break;
if (!r_idx || !attempts) return;
/* Note the alignment */
- if (r_info[r_idx].flags3 & RF3_GOOD) align++;
- else if (r_info[r_idx].flags3 & RF3_EVIL) align--;
+ if (r_ptr->flags3 & RF3_EVIL) align.sub_align |= SUB_ALIGN_EVIL;
+ if (r_ptr->flags3 & RF3_GOOD) align.sub_align |= SUB_ALIGN_GOOD;
what[i] = r_idx;
}