Update Units::isCitizen after looking at game-over detection code.

develop
Alexander Gavrilov 2012-05-22 12:31:37 +04:00
parent 20794ebf19
commit 9adf310d7f
5 changed files with 86 additions and 13 deletions

@ -726,7 +726,7 @@ Units module
* ``dfhack.units.isDead(unit)`` * ``dfhack.units.isDead(unit)``
The unit is completely dead and passive. The unit is completely dead and passive, or a ghost.
* ``dfhack.units.isAlive(unit)`` * ``dfhack.units.isAlive(unit)``
@ -734,7 +734,16 @@ Units module
* ``dfhack.units.isSane(unit)`` * ``dfhack.units.isSane(unit)``
The unit is capable of rational action, i.e. not dead, insane or zombie. The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.
* ``dfhack.units.isDwarf(unit)``
The unit is of the correct race of the fortress.
* ``dfhack.units.isCitizen(unit)``
The unit is an alive sane citizen of the fortress; wraps the
same checks the game uses to decide game-over by extinction.
* ``dfhack.units.getAge(unit[,true_age])`` * ``dfhack.units.getAge(unit[,true_age])``

@ -960,13 +960,20 @@ a lua list containing them.</p>
<p>Returns the nemesis record of the unit if it has one, or <em>nil</em>.</p> <p>Returns the nemesis record of the unit if it has one, or <em>nil</em>.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.units.isDead(unit)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.units.isDead(unit)</tt></p>
<p>The unit is completely dead and passive.</p> <p>The unit is completely dead and passive, or a ghost.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.units.isAlive(unit)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.units.isAlive(unit)</tt></p>
<p>The unit isn't dead or undead.</p> <p>The unit isn't dead or undead.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.units.isSane(unit)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.units.isSane(unit)</tt></p>
<p>The unit is capable of rational action, i.e. not dead, insane or zombie.</p> <p>The unit is capable of rational action, i.e. not dead, insane, zombie, or active werewolf.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.units.isDwarf(unit)</tt></p>
<p>The unit is of the correct race of the fortress.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.units.isCitizen(unit)</tt></p>
<p>The unit is an alive sane citizen of the fortress; wraps the
same checks the game uses to decide game-over by extinction.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.units.getAge(unit[,true_age])</span></tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.units.getAge(unit[,true_age])</span></tt></p>
<p>Returns the age of the unit in years as a floating-point value. <p>Returns the age of the unit in years as a floating-point value.

@ -715,6 +715,8 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = {
WRAPM(Units, isDead), WRAPM(Units, isDead),
WRAPM(Units, isAlive), WRAPM(Units, isAlive),
WRAPM(Units, isSane), WRAPM(Units, isSane),
WRAPM(Units, isDwarf),
WRAPM(Units, isCitizen),
WRAPM(Units, getAge), WRAPM(Units, getAge),
WRAPM(Units, getProfessionName), WRAPM(Units, getProfessionName),
WRAPM(Units, getCasteProfessionName), WRAPM(Units, getCasteProfessionName),

@ -613,12 +613,45 @@ df::nemesis_record *Units::getNemesis(df::unit *unit)
return NULL; return NULL;
} }
static bool casteFlagSet(int race, int caste, df::caste_raw_flags flag)
{
auto creature = df::creature_raw::find(race);
if (!creature)
return false;
auto craw = vector_get(creature->caste, caste);
if (!craw)
return false;
return craw->flags.is_set(flag);
}
static bool isCrazed(df::unit *unit)
{
if (unit->flags3.bits.scuttle)
return false;
if (unit->curse.rem_tags1.bits.CRAZED)
return false;
if (unit->curse.add_tags1.bits.CRAZED)
return true;
return casteFlagSet(unit->race, unit->caste, caste_raw_flags::CRAZED);
}
static bool isOpposedToLife(df::unit *unit)
{
if (unit->curse.rem_tags1.bits.OPPOSED_TO_LIFE)
return false;
if (unit->curse.add_tags1.bits.OPPOSED_TO_LIFE)
return true;
return casteFlagSet(unit->race, unit->caste, caste_raw_flags::CANNOT_UNDEAD);
}
bool DFHack::Units::isDead(df::unit *unit) bool DFHack::Units::isDead(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
return unit->flags1.bits.dead; return unit->flags1.bits.dead ||
unit->flags3.bits.ghostly;
} }
bool DFHack::Units::isAlive(df::unit *unit) bool DFHack::Units::isAlive(df::unit *unit)
@ -636,8 +669,11 @@ bool DFHack::Units::isSane(df::unit *unit)
if (unit->flags1.bits.dead || if (unit->flags1.bits.dead ||
unit->flags3.bits.ghostly || unit->flags3.bits.ghostly ||
unit->curse.add_tags1.bits.OPPOSED_TO_LIFE || isOpposedToLife(unit) ||
unit->curse.add_tags1.bits.CRAZED) unit->unknown8.unk2)
return false;
if (unit->unknown8.normal_race == unit->unknown8.were_race && isCrazed(unit))
return false; return false;
switch (unit->mood) switch (unit->mood)
@ -657,19 +693,38 @@ bool DFHack::Units::isCitizen(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
// Copied from the conditions used to decide game over,
// except that the game appears to let melancholy/raving
// dwarves count as citizens.
if (!isDwarf(unit) || !isSane(unit))
return false;
if (unit->flags1.bits.marauder ||
unit->flags1.bits.invader_origin ||
unit->flags1.bits.active_invader ||
unit->flags1.bits.forest ||
unit->flags1.bits.merchant ||
unit->flags1.bits.diplomat)
return false;
if (unit->flags1.bits.tame)
return true;
return unit->civ_id == ui->civ_id && return unit->civ_id == ui->civ_id &&
!unit->flags1.bits.merchant && unit->civ_id != -1 &&
!unit->flags1.bits.diplomat && !unit->flags2.bits.underworld &&
!unit->flags2.bits.resident && !unit->flags2.bits.resident &&
!unit->flags1.bits.dead && !unit->flags2.bits.visitor_uninvited &&
!unit->flags3.bits.ghostly; !unit->flags2.bits.visitor;
} }
bool DFHack::Units::isDwarf(df::unit *unit) bool DFHack::Units::isDwarf(df::unit *unit)
{ {
CHECK_NULL_POINTER(unit); CHECK_NULL_POINTER(unit);
return unit->race == ui->race_id; return unit->race == ui->race_id ||
unit->unknown8.normal_race == ui->race_id;
} }
double DFHack::Units::getAge(df::unit *unit, bool true_age) double DFHack::Units::getAge(df::unit *unit, bool true_age)

@ -1 +1 @@
Subproject commit 234d0f57a927f306f2052fc2f45d38b3201ddee6 Subproject commit d991d47b0f6709205c4e333bb86edb3dcf656429