Also:
In my last commit I forgot to mention that the descriptions were suggested by Richard Gould, and I'd like to give credit where credit is due. :)
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2005 c06c8d41-db1a-0410-9941-cceddc491573
Z6XF4AIERIW4U4AR3HU2ILYFZ54IK4K4ORQ6JKCEWRO5LZODWDDAC
SEQIMAWXQYBD6UWTK5HYN4KGLLV53HFM3LLQRSG4N5ZVZTLPR22QC
3BYA46OYLVN6ZPGAZD5OGIMMH5PRWGNSU3ITJRCVBE6P5HYYYAYQC
LZBHBSCXDX2JKU2BSO5QP3WDHFIGHPXK4CKUZV6FWYDRFWLQK26QC
2N5AKUYV6EUUT254C47WSHZKD7FGN65JKJ3RCKSDP74XJIHIFMDQC
ESWIM76FGJL4QFLSHU6AC4D74PT7OPLQ7ZCJYWLZS5UCBAJDXYHAC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC
IHIJSWVOONSTA2WCHKW3YKBLETUQECFVBVLMET5SGQZ4C6U3GCUQC
PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC
TRNEOO3YKZSUGYTJZDDXZTJFQJXY6PWKBDJXAOLY3FZAD6WHTUTQC
6HQB2N6N75R2RGKJFWRUN7WAC2PNGWQFXTII5DTRLTHZ2BOTMTVAC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
YQ5IYBHW2ICYKOC2M6CI5BNOZKST3DIMMZRQN72LUQCHDAPVYQCQC
U3KGUJJQWQORJIIFH3ADVNIEEX5HOX6KEOXO7DJSL7L3Z6GG3PAQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
IXVKL2SINZN4DMJSZSYFVK5YLGSBGV4KCN7GKYQL7SZQDCM3S7YQC
RSIUBEQUGNU4LO6KH4PKVROWQS33DAKSY4XFVGN7T3CEKSXABCSAC
X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC
void tutorial_describe_item(item_def& item);
bool tutorial_feat_interesting(int feat);
void tutorial_describe_feature(int feat);
// additional information for tutorial players
void tutorial_describe_item(item_def &item);
bool tutorial_feat_interesting(dungeon_feature_type feat);
void tutorial_describe_feature(dungeon_feature_type feat);
bool tutorial_monster_interesting(const monsters *mons);
void tutorial_describe_monster(const monsters *mons);
"<lightgray>b<magenta> or <brown>K<magenta>. ";
if (get_mons_colour(&mon) != (&mon)->colour)
learned_something_new(TUT_MONSTER_BRAND);
else
{
text += "You can gain information about it by pressing <w>x<magenta> "
"and moving the cursor on the monster.";
}
text += "\nTo attack this monster with your wielded weapon, just move into "
"<lightgray>b<magenta> or <brown>K<magenta>. You can gain information "
"about it by pressing <w>x<magenta> and moving the cursor on the "
"monster."
"\nTo attack this monster with your wielded weapon, just move into "
result = "You'll then find yourself in target mode with the nearest monster "
"or previous target already targetted. You can also cycle through "
"all hostile monsters in sight with <w>+<magenta> or <w>-<magenta>. "
result = "then be taken to target mode with the nearest monster or previous "
"target already targetted. You can also cycle through all hostile "
"monsters in sight with <w>+<magenta> or <w>-<magenta>. "
ostr << "You can wear pieces of armour with <w>W<magenta> and take "
"them off again with <w>T<magenta>. ";
{
bool wearable = true;
if (you.species == SP_CENTAUR && item.sub_type == ARM_BOOTS)
{
ostr << "As a Centaur you cannot wear boots.";
wearable = false;
}
else if (you.species == SP_MINOTAUR && item.sub_type == ARM_HELMET
&& get_helmet_type(item) != THELM_CAP
&& get_helmet_type(item) != THELM_WIZARD_HAT)
{
ostr << "As a Minotaur you cannot wear helmets.";
wearable = false;
}
else
{
ostr << "You can wear pieces of armour with <w>W<magenta> and take "
"them off again with <w>T<magenta>.";
}
ostr << "Do this as follows: Type <w>Z<magenta>, then "
"choose the spell you want to cast (with "
"<w>?<magenta>), for example <w>a<magenta>, "
"which is the first spell you know, "
<< spell_title(get_spell_by_letter('a'))
<< ". ";
ostr << tut_target_mode(true);
if (player_can_memorize(item))
{
ostr << "Such a <lightblue>highlighted spell<magenta> "
"can be <w>M<magenta>emorized right away. ";
}
else
{
ostr << "You cannot memorize any "
<< (you.spell_no ? "more " : "")
<< "spells right now. This will change as you "
"grow in levels and Spellcasting proficiency. ";
}
if (you.spell_no)
{
ostr << "\n\nTo do magic, type <w>Z<magenta> and "
"choose a spell (check with <w>?<magenta>). "
"For attack spells you'll ";
ostr << tut_target_mode(true);
}
break;
case DNGN_ALTAR_ZIN:
case DNGN_ALTAR_SHINING_ONE:
case DNGN_ALTAR_KIKUBAAQUDGHA:
case DNGN_ALTAR_YREDELEMNUL:
case DNGN_ALTAR_XOM:
case DNGN_ALTAR_VEHUMET:
case DNGN_ALTAR_OKAWARU:
case DNGN_ALTAR_MAKHLEB:
case DNGN_ALTAR_SIF_MUNA:
case DNGN_ALTAR_TROG:
case DNGN_ALTAR_NEMELEX_XOBEH:
case DNGN_ALTAR_ELYVILON:
case DNGN_ALTAR_LUGONU:
case DNGN_ALTAR_BEOGH:
{
god_type altar_god = grid_altar_god(feat);
if (you.religion == GOD_NO_GOD)
{
ostr << "This is your chance to join a religion! In general, the "
"gods will help their followers, bestowing powers of all "
"sorts upon them, but many of them demand a life of "
"dedication, constant tributes or entertainment in return. "
"\nYou can get information about <w>"
<< god_name(altar_god)
<< "<magenta> by pressing <w>p<magenta> while standing on "
"the altar. Before taking up the responding faith you'll "
"be asked for confirmation.";
}
else
{
if (you.religion == altar_god)
{
ostr << "If "
<< god_name(you.religion)
<< " likes to have items or corpses sacrificed on altars, "
"here you can do this by <w>d<magenta>ropping them, "
"then <w>p<magenta>raying. As a follower, pressing "
"<w>^<magenta> allows you to check "
<< god_name(you.religion)
<< "'s likes and dislikes at any time.";
}
else
{
ostr << god_name(you.religion)
<< " probably won't like it if you switch allegiance, "
"but having a look won't hurt: to get information on <w>";
ostr << god_name(altar_god);
ostr << "<magenta>, press <w>p<magenta> while standing on the "
"altar. Before taking up the responding faith (and "
"abandoning your current one!) you'll be asked for "
"confirmation."
"\nTo see your current standing with "
<< god_name(you.religion)
<< " press <w>^<magenta>.";
}
}
Options.tutorial_events[TUT_SEEN_ALTAR];
break;
}
case DNGN_ENTER_ORCISH_MINES:
case DNGN_ENTER_HIVE:
case DNGN_ENTER_LAIR:
case DNGN_ENTER_SLIME_PITS:
case DNGN_ENTER_VAULTS:
case DNGN_ENTER_CRYPT:
case DNGN_ENTER_HALL_OF_BLADES:
case DNGN_ENTER_ZOT:
case DNGN_ENTER_TEMPLE:
case DNGN_ENTER_SNAKE_PIT:
case DNGN_ENTER_ELVEN_HALLS:
case DNGN_ENTER_TOMB:
case DNGN_ENTER_SWAMP:
case DNGN_ENTER_SHOALS:
ostr << "An entryway into one of the many dungeon branches in Crawl. ";
if (feat != DNGN_ENTER_TEMPLE)
ostr << "Beware, sometimes these can be deadly!";
} // tutorial_describe_feature
bool tutorial_monster_interesting(const monsters *mons)
{
// highlighted in some way
if (get_mons_colour(mons) != mons->colour)
return true;
// monster is (seriously) out of depth
if (you.level_type == LEVEL_DUNGEON &&
mons_level(mons->type) >= you.your_level + Options.ood_interesting)
{
return true;
}
return false;
void tutorial_describe_monster(const monsters *mons)
{
std::ostringstream ostr;
ostr << "<magenta>";
int level_diff
= mons_level(mons->type) - (you.your_level + Options.ood_interesting);
if (you.level_type == LEVEL_DUNGEON && level_diff >= 0)
{
ostr << "This kind of monster is usually only encountered "
<< (level_diff > 5 ? "much " : "")
<< "deeper in the dungeon, so it's probably "
<< (level_diff > 5 ? "extremely" : "very")
<< " dangerous!\n\n";
}
if (mons->has_ench(ENCH_BERSERK))
ostr << "A berserking monster is bloodthirsty and fighting madly.\n";
if (mons_friendly(mons))
{
ostr << "Friendly monsters will follow you around and attempt to aid "
"you in battle.";
}
else if (Options.stab_brand != CHATTR_NORMAL
&& mons_looks_stabbable(mons))
{
ostr << "Apparently it has not noticed you - yet.";
}
else if (Options.may_stab_brand != CHATTR_NORMAL
&& mons_looks_distracted(mons))
{
ostr << "Apparently it has been distracted by something.";
}
std::string broken = ostr.str();
linebreak_string2(broken, get_tutorial_cols());
formatted_string::parse_block(broken, false).display();
} // tutorial_describe_monster
bool player_can_memorize(item_def &book)
{
if (book.base_type != OBJ_BOOKS || book.sub_type == BOOK_MANUAL)
return false;
if (!player_spell_levels())
return false;
for (int j = 0; j < SPELLBOOK_SIZE; j++)
{
const spell_type stype = which_spell_in_book(book.book_number(), j);
if (stype == SPELL_NO_SPELL)
continue;
// easiest spell already too difficult
if (spell_difficulty(stype) > you.experience_level
|| player_spell_levels() < spell_levels_required(stype))
{
return false;
}
bool knowsSpell = false;
for (int i = 0; i < 25 && !knowsSpell; i++)
{
knowsSpell = (you.spells[i] == stype);
}
// don't already know this spell
if (!knowsSpell)
{
return true;
}
}
return false;
}
snprintf(buf, sizeof buf,
"%-7s: <lightgray>(ill-fitting)</lightgray>", slot);
if (!you_tran_can_wear(e_order[i]))
{
snprintf(buf, sizeof buf, "%-7s: "
"<darkgray>(currently unavailable)</darkgray>",
slot);
}
else
{ snprintf(buf, sizeof buf,
"%-7s: <lightgray>(ill-fitting)</lightgray>",
slot);
}
}
bool gives_ability( const item_def &item )
{
if (!item_type_known(item))
return false;
switch (item.base_type)
{
case OBJ_WEAPONS:
{
// unwielded weapon
item_def *weap = you.slot_item(EQ_WEAPON);
if (!weap || (*weap).slot != item.slot)
return false;
break;
}
case OBJ_JEWELLERY:
{
if (item.sub_type < NUM_RINGS)
{
// unworn ring
item_def *lring = you.slot_item(EQ_LEFT_RING);
item_def *rring = you.slot_item(EQ_RIGHT_RING);
if ((!lring || (*lring).slot != item.slot)
&& (!rring || (*rring).slot != item.slot))
{
return false;
}
if (item.sub_type == RING_TELEPORTATION
|| item.sub_type == RING_LEVITATION
|| item.sub_type == RING_INVISIBILITY)
{
return true;
}
}
else
{
// unworn amulet
item_def *amul = you.slot_item(EQ_AMULET);
if (!amul || (*amul).slot != item.slot)
return false;
if (item.sub_type == AMU_RAGE)
return true;
}
break;
}
case OBJ_ARMOUR:
{
const equipment_type eq = get_armour_slot(item);
if (eq == EQ_NONE)
return false;
// unworn armour
item_def *arm = you.slot_item(eq);
if (!arm || (*arm).slot != item.slot)
return false;
break;
}
default:
return false;
}
if (!is_random_artefact(item))
return false;
// check for evokable randart properties
for (int rap = RAP_INVISIBLE; rap <= RAP_MAPPING; rap++)
{
if (randart_wpn_property( item, rap ))
return true;
}
return false;