in a net, specific skills, magic resistance, and which stat to choose.
In a given game you'll only ever see a small fraction of all tutorial events (we're at 71 now, and some of them are exclusive). In fact, a lot of the information is so generally useful (esp. on gods, skills and items) that I'm seriously considering opening up the general information (How do I use item x? What does Spellcasting do?) to a wider selection of characters. I don't think we'll want to explain the intricacies of Mummies, Ghouls, or Vampires, but a lot of this stuff even applies to them… (If we overhaul the tutorial, it's certainly not a 0.4 target, though.)
Resetting the tutorial version to 8 as we somehow switched from digital version to binary and back to digital. It will take some time until we actually reach 110, and by then, I am sure the base files won't be save compatible anymore. :)
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5777 c06c8d41-db1a-0410-9941-cceddc491573
JBZ7NU4BB5PGQWCOSZHD5OQUHQIVOD4XGJLSJQ7BUGQEGPRTVGZQC
XTTCWZRQLSIEK7NUYUHSTSCGQANKZSTE5HTZGTTNTQUYSSICEQBAC
VJZ4D26E4L4E22SO6UYB44DNUTLG72LA4GTAEZ2DKKEMAICHOXBQC
S6S2RKQWW5VKC4YW6N6LOLGPWT7T3XIP4LLP2QOHN4NYRNFKKJMQC
QDUHZS53FZKXUT7AV3IETPDKJU4IG2X7BGTF7TLACIP2FVPFCUMAC
5FMXUX2ZFIF6NQZCS54W7ZOCVSH7XR6UIMQ5FW2UZLEN4EWP5PSAC
C5U3HSOOQ7BKXKXIDS7MLVXUKDTHAWJ5NXNX6YDXTM3GWY5UWX4QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
IHIJSWVOONSTA2WCHKW3YKBLETUQECFVBVLMET5SGQZ4C6U3GCUQC
QXD3HX6QQ37PW6HVKIIKGFLO2ACROLUGKK66KFX7ED6SO4FDXB2AC
Z6XF4AIERIW4U4AR3HU2ILYFZ54IK4K4ORQ6JKCEWRO5LZODWDDAC
BFCFMN2BXNLXJCYYCL2V2XTDQQNM3PJPSRB6CU76FM3332NC7GMAC
L3DRKFURVDCV3EJKGG6GVVQX3D5MZPICTVOKNOD3LGM2PECBA7PQC
IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC
7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC
HQTS3VQ6PNUZKHNVEWMML7JNAAAKL4DSW3KFSRCCSLGYTDHZFCCAC
WMSWIUXVDVHMW2QQFDZNWXDUYWW2UO7FGTNDAJA3Y6N2PLFXPNHQC
WF2DSJGR6PKLGQSXEFF4ZW4EZZFGMHXPXWUYAKYBPFJH6KJKAANQC
ESWIM76FGJL4QFLSHU6AC4D74PT7OPLQ7ZCJYWLZS5UCBAJDXYHAC
W54GZBNFKPOF6DTOVK73PVASTQI5DXG42WQ6CXFDPXHFZOHUVVSQC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
NK2TBKWOQBD2ZRGAO4Z3HMZPIN7UX3HNUS2YHEIJUUINUTRMPODQC
6HQB2N6N75R2RGKJFWRUN7WAC2PNGWQFXTII5DTRLTHZ2BOTMTVAC
U3KGUJJQWQORJIIFH3ADVNIEEX5HOX6KEOXO7DJSL7L3Z6GG3PAQC
HMC247EGUJ3Q25DQ3VKUCIGLIO4SZORFQQWAPAF6S2WLQY3WU5TQC
TRNEOO3YKZSUGYTJZDDXZTJFQJXY6PWKBDJXAOLY3FZAD6WHTUTQC
TI2HASZUN3QBTNWRCXLXJHOZBOUHFEOQUCPK5EYLATL7BP32H6LQC
ACDPN464TK2LKLHSDN3YVRHAPF7WLSLLU3UHIYEXKFDEZPEU3XSQC
LS5XCCGKQHSJQGWLWLGTP2F5OYWK4ND5AQQAGRN6H2HVBSXNCCZAC
PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC
5HF63O5IRRERI2V3SZEDHUNFHUF2B4RSVWQR6C6DR5JF5UYSROWAC
7HA2754QW3SBCAJ5K6KUXNXXXIZB5BIBCFPLXADCXHH6EREKXHSAC
MCBXXIV6GICTZB56APSXMJEI63FVQWVZR3H2DRNMMFDH2XCGK4JAC
HNX5L5QUZWBQTOBEVKJTAMRX5NOCK7CVBIKMCLYEJLVJNCCUCXUAC
T47R62M4FQ7O6JBKXKLPSZD5JZWLJKFBGTHHQ5ZXCCTAX4QNFKAAC
TO43FWKHNIA5MVDOFXYHQODTLBQYEZKX5UIUGID57436UF7G2EXQC
2N5AKUYV6EUUT254C47WSHZKD7FGN65JKJ3RCKSDP74XJIHIFMDQC
GL6SGPBZQPJBVGPOASYVCTAFXS7RNARR6Y5WZMIO5YCTB7ZJY4KAC
PZNRGNZPN4YLXL2UDMEUPE33AAZZ6Z2YPK6EQGYZL2PNTRWLCUNQC
Q4YYTFXYZUDBYWT37U354CJOAQMAAIWM5W72TAEGMEUKZIUZBMGAC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC
BOJPQUU6D4LHA2PGXUZBGTOW54G7ISKFXC4UQHLBSVAI7KQGYW6QC
TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC
3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC
3GRGONHWIZ7PTTNMJ6CIZEMIKC7N2DTU62BLJ5QG4E7RGA5O2XMAC
POP6UTTHSJGDU5NU7ENQJOZVFUHYM63HJ6HLPXDDLK7XFIP4XEIQC
SJP5BHX6MFWF3OSQPEF4WUWZWPUGMOVURTT2CUVT6H3A66LETXUAC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
4GYZYBY7FFORRNPIEFTV4ZM2C7Z6D2KTQOM537ZCC2YBXT2TNSHAC
WZNB427K3EUNV3FMVXLQTM4UIHER4FIKQXWLUUXRNQC3OQ33VQYAC
WNDCC2WZEUQ2SHRQZUAAK3A4QF5JGLDJ5D3WLKLNXYSCK4TZ7KZAC
MDFQRJ6QZNFUBVSFWLXUJ6EBXOU47T3CVDI2XKBGNNRF4DXDKESQC
C7Q5QY7S5TTMJ3XO2SIO3FY5ZENWYYETS4NKEKCAJMENEHJC6Y2AC
KYVZGUJXV23ELA4CKPVQZO3NTJCODXMCWYAZJYWVWJVLPETNHLGQC
V4DWL5WBO2JCODVS5QQNWXDH4DAYZN3D5V3UDCHM2KKOMADOTEDQC
TPSCOEB3X6LNZ7F5UBMHDZ4IUE4H3RLX6IGNW65VSJBDMNNZ3FMAC
Y3N66XTY5HEWDFX2UV2KK4JFLZ3GTFAFBYPD7IHWCBBGMR6EJ6XAC
WF3F2I73VYD5BGLTUC3YWXZQ3CN2H2ZPBH2R7WJ5WQLHJSUYGU5QC
ZBPS5ZTPF3DVTR5WET4XEFHYXU26CRHU2OHX3YO6PD4MTM2DUXAQC
FALRUC4VFHW2E6ANXG6MHJZOTXDZJ7SY3CAJB23LQH7L35V4JPPAC
PGTE3JC4J5U536IJTCJFXTUOSRE73JXZJINWAGCANOQOCGC7J6AAC
AO7VKBS75RKHQDP3KYUVNMCE562K7NMVO2W3YXH7D5DKMKGO5GOQC
LH4OYDEWEON5QNUCM74R7MNBJDP7O4XRETY74ZMYSXUXYQV427PAC
Y4NA3JSN63RLATF4NNBPSR5CWF5Z7UEMWCGVX4B6NOAR47CGM4GQC
JYCMD6WMNHXA53K4LLKVTNX6PLRLU25F6J2TYMPQXM2ENAE66NIAC
VNIAJEGE3PYE6F6EAMCQDWMAS52EQTKJUPAFXK7ARCITZ326WTTQC
Q5YUZONIIPGRWOIQNL6DHRGLKF4V3K5XSZCBH2SL7DP4WPLDNOSQC
5FBOE2QNRLKUNOP54CZD6LFAMM7LX6NNLHJRJHRDDIUTQ7J723DQC
MDAJYB6STTZPNHRQ2X66MMMSONMKXTESLHJSFPGN7H3D3TOVBAVAC
KFWX5LI235XQYQOSUSSAKKQUNB2OCN3NOYP6E7D3HSM2UOSBGYHQC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
OFH2B2UZBK43QLFQBZ54FOCFLFNE54BZVDNCEUGDTBCUGNVZULIQC
U6Q43EFKHJIDBBWN6RUTOYRHHX4IT73OPBR4CWIOKUDGTCYQE5PAC
JCWJWGMQIKQGSSFJUQRKNIWW3HBOJSHYDTOPPE5BWOJTIJTDYUTAC
FU663V7RFZNSMG5P2E7TZJZWSGXWLCCFXSVGH4Z222FIJTH4R3KAC
UFKLHUYL7WAQ3CI3D42T4C6KBGAUR63DSQAUQTTZG7GJMXSCVJWAC
SBTVKHKZRMVDBYLGQNMZMJXPAYJG43UWBBD7HQJWIPN3BMMHUBJAC
P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC
SJOTTUZMA3UTGT5D6LKUTBDP2CZFXT24FB5IAWCUFHSHLLACM75QC
QYQKV4R47PTERXVFQNNWWQVICGSOMBHW6WM5TAZAKLIYOLLPUAJAC
FZKMVCODMWQEVVBBQHTTXFBRO4LZEYLB646ZPVUMLHH6EER7FAOAC
VCG3BRIYRTNNWYC3LOXD6KFGXOX37HAFW2HNV7WXVG2V7EUHLDZQC
NGW2XPEX2XRK3CYC37DNUZSSB5IQLECMKRB6NX257I2X3G35LMPAC
DMG73XDQHY2X2PHKWIY56XKD3O4NPGZKKIO6GX3IV2LLRVXPGKYQC
GVW4OBPGXY2Q75HB7QHADZIOHKL22FI2BSJ2TM4K5SBJENBFTQKAC
G5WLU3B4MR3ZDJLGR6OHNIMLZXGQS2EWBJ5YYY5J2GWM6DTD44BAC
BMHUBADDGIOZRVN4P3O5QKIDUYD4RFWBS7MP5X6LZWAYHUBRVD2QC
CH7JECYYH35H4TRHRNRTRJCQTQLZ2WRH62TKV72SUIU2RTK5OH7AC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
WCAOZXOYYQBLVRS5FRZTP5ZFOYLQCCPWHGIFM2DLVGHIKVYSQVWQC
O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC
JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
EHP6PYCIPYQ3KF4JFGBTZXEUQHN3FVAH4NUWEOWDDNKGPYVOTOJQC
ANOEQTM6IGCBTESKKQ5PCBSDTZ7VGRCMDIOAFEH4R7DJHKWKDFAAC
S7DVJRHOA2DESNNM77EJYG3GVVOQW7SUNEXMNOLZRFJERKCPS2OQC
QRD2M37AMG76CPGCALZQ3N2PZ3OZ3MFETMVAEHBJJVVH2BCPVGUAC
BIZDHHK5LIO57S5AKHEPJFLWV5DAFKZIKYBGOUNGICSWTX7DCXKAC
NLXVJSK53M3GCGGVJWYPHYZJ2A7JAF2FEYQPIGLRUYJ3FTWYONLQC
4HLF6Q3OBOOHCCJ76L2BXVIYI6EMJ2G7O4XXZPFTLFP6BQGSUZNAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
case TUT_SEEN_FIRST_OBJECT:
return "seen first object";
case TUT_SEEN_POTION:
return "seen first potion";
case TUT_SEEN_SCROLL:
return "seen first scroll";
case TUT_SEEN_WAND:
return "seen first wand";
case TUT_SEEN_SPBOOK:
return "seen first spellbook";
case TUT_SEEN_WEAPON:
return "seen first weapon";
case TUT_SEEN_MISSILES:
return "seen first missiles";
case TUT_SEEN_ARMOUR:
return "seen first armour";
case TUT_SEEN_RANDART:
return "seen first random artefact";
case TUT_SEEN_FOOD:
return "seen first food";
case TUT_SEEN_CARRION:
return "seen first corpse";
case TUT_SEE_GOLD:
return "seen first pile of gold";
case TUT_SEEN_JEWELLERY:
return "seen first jewellery";
case TUT_SEEN_MISC:
return "seen first misc. item";
case TUT_SEEN_MONSTER:
return "seen first monster";
case TUT_SEEN_STAIRS:
return "seen first stairs";
case TUT_SEEN_ESCAPE_HATCH:
return "seen first escape hatch";
case TUT_SEEN_BRANCH:
return "seen first branch entrance";
case TUT_SEEN_TRAP:
return "encountered a trap";
case TUT_SEEN_ALTAR:
return "seen an altar";
case TUT_SEEN_SHOP:
return "seen a shop";
case TUT_SEEN_DOOR:
return "seen a closed door";
case TUT_SEEN_SECRET_DOOR:
return "found a secret door";
case TUT_KILLED_MONSTER:
return "killed first monster";
case TUT_NEW_LEVEL:
return "gained a new level";
case TUT_SKILL_RAISE:
return "raised a skill";
case TUT_YOU_ENCHANTED:
return "caught an enchantment";
case TUT_YOU_SICK:
return "became sick";
case TUT_YOU_POISON:
return "were poisoned";
case TUT_YOU_ROTTING:
return "were rotting";
case TUT_YOU_CURSED:
return "had something cursed";
case TUT_YOU_HUNGRY:
return "felt hungry";
case TUT_YOU_STARVING:
return "were starving";
case TUT_MAKE_CHUNKS:
return "learned about chunks";
case TUT_OFFER_CORPSE:
return "learned about sacrifice";
case TUT_MULTI_PICKUP:
return "read about pickup menu";
case TUT_HEAVY_LOAD:
return "were encumbered";
case TUT_ROTTEN_FOOD:
return "carried rotten food";
case TUT_NEED_HEALING:
return "needed healing";
case TUT_NEED_POISON_HEALING:
return "needed healing for poison";
case TUT_INVISIBLE_DANGER:
return "encountered an invisible foe";
case TUT_NEED_HEALING_INVIS:
return "had to heal near an unseen monster";
case TUT_ABYSS:
return "was cast into the Abyss";
case TUT_POSTBERSERK:
return "learned about Berserk aftereffects";
case TUT_RUN_AWAY:
return "were told to run away";
case TUT_RETREAT_CASTER:
return "were told to retreat as a caster";
case TUT_SHIFT_RUN:
return "learned about shift-run";
case TUT_MAP_VIEW:
return "learned about the level map";
case TUT_DONE_EXPLORE:
return "explored a level";
case TUT_YOU_MUTATED:
return "caught a mutation";
case TUT_NEW_ABILITY:
return "gained a divine ability";
case TUT_WIELD_WEAPON:
return "wielded an unsuitable weapon";
case TUT_FLEEING_MONSTER:
return "made a monster flee";
case TUT_MONSTER_BRAND:
return "learned about colour brandings";
case TUT_MONSTER_FRIENDLY:
return "seen first friendly monster";
case TUT_CONVERT:
return "converted to a god";
case TUT_GOD_DISPLEASED:
return "piety ran low";
case TUT_EXCOMMUNICATE:
return "excommunicated by a god";
case TUT_SPELL_MISCAST:
return "spell miscast";
case TUT_SPELL_HUNGER:
return "spell casting caused hunger";
case TUT_GLOWING:
return "player glowing from contamination";
case TUT_STAIR_BRAND:
return "saw stairs with objects on it";
default:
return "faced a bug";
case TUT_SEEN_FIRST_OBJECT:
return "seen first object";
case TUT_SEEN_POTION:
return "seen first potion";
case TUT_SEEN_SCROLL:
return "seen first scroll";
case TUT_SEEN_WAND:
return "seen first wand";
case TUT_SEEN_SPBOOK:
return "seen first spellbook";
case TUT_SEEN_WEAPON:
return "seen first weapon";
case TUT_SEEN_MISSILES:
return "seen first missiles";
case TUT_SEEN_ARMOUR:
return "seen first armour";
case TUT_SEEN_RANDART:
return "seen first random artefact";
case TUT_SEEN_FOOD:
return "seen first food";
case TUT_SEEN_CARRION:
return "seen first corpse";
case TUT_SEE_GOLD:
return "seen first pile of gold";
case TUT_SEEN_JEWELLERY:
return "seen first jewellery";
case TUT_SEEN_MISC:
return "seen first misc. item";
case TUT_SEEN_MONSTER:
return "seen first monster";
case TUT_SEEN_STAIRS:
return "seen first stairs";
case TUT_SEEN_ESCAPE_HATCH:
return "seen first escape hatch";
case TUT_SEEN_BRANCH:
return "seen first branch entrance";
case TUT_SEEN_TRAP:
return "encountered a trap";
case TUT_SEEN_ALTAR:
return "seen an altar";
case TUT_SEEN_SHOP:
return "seen a shop";
case TUT_SEEN_DOOR:
return "seen a closed door";
case TUT_SEEN_SECRET_DOOR:
return "found a secret door";
case TUT_KILLED_MONSTER:
return "killed first monster";
case TUT_NEW_LEVEL:
return "gained a new level";
case TUT_SKILL_RAISE:
return "raised a skill";
case TUT_YOU_ENCHANTED:
return "caught an enchantment";
case TUT_YOU_SICK:
return "became sick";
case TUT_YOU_POISON:
return "were poisoned";
case TUT_YOU_ROTTING:
return "were rotting";
case TUT_YOU_CURSED:
return "had something cursed";
case TUT_YOU_HUNGRY:
return "felt hungry";
case TUT_YOU_STARVING:
return "were starving";
case TUT_MAKE_CHUNKS:
return "learned about chunks";
case TUT_OFFER_CORPSE:
return "learned about sacrifice";
case TUT_MULTI_PICKUP:
return "read about pickup menu";
case TUT_HEAVY_LOAD:
return "were encumbered";
case TUT_ROTTEN_FOOD:
return "carried rotten food";
case TUT_NEED_HEALING:
return "needed healing";
case TUT_NEED_POISON_HEALING:
return "needed healing for poison";
case TUT_INVISIBLE_DANGER:
return "encountered an invisible foe";
case TUT_NEED_HEALING_INVIS:
return "had to heal near an unseen monster";
case TUT_ABYSS:
return "was cast into the Abyss";
case TUT_POSTBERSERK:
return "learned about Berserk after-effects";
case TUT_RUN_AWAY:
return "were told to run away";
case TUT_RETREAT_CASTER:
return "were told to retreat as a caster";
case TUT_SHIFT_RUN:
return "learned about shift-run";
case TUT_MAP_VIEW:
return "learned about the level map";
case TUT_DONE_EXPLORE:
return "explored a level";
case TUT_YOU_MUTATED:
return "caught a mutation";
case TUT_NEW_ABILITY:
return "gained a divine ability";
case TUT_WIELD_WEAPON:
return "wielded an unsuitable weapon";
case TUT_FLEEING_MONSTER:
return "made a monster flee";
case TUT_MONSTER_BRAND:
return "learned about colour brandings";
case TUT_MONSTER_FRIENDLY:
return "seen first friendly monster";
case TUT_CONVERT:
return "converted to a god";
case TUT_GOD_DISPLEASED:
return "piety ran low";
case TUT_EXCOMMUNICATE:
return "excommunicated by a god";
case TUT_SPELL_MISCAST:
return "spell miscast";
case TUT_SPELL_HUNGER:
return "spell casting caused hunger";
case TUT_GLOWING:
return "player glowing from contamination";
case TUT_STAIR_BRAND:
return "saw stairs with objects on it";
case TUT_YOU_RESIST:
return "resisted some magic";
case TUT_CAUGHT_IN_NET:
return "were caught in a net";
case TUT_LOAD_SAVED_GAME:
return "restored a saved game";
case TUT_GAINED_MAGICAL_SKILL:
return "gained a new magical skill";
case TUT_CHOOSE_STAT:
return "could choose a stat";
case TUT_CAN_BERSERK:
return "were told to Berserk";
default:
return "faced a bug";
}
}
// Give a special message if you gain a skill you didn't have before.
void tut_gained_new_skill(int skill)
{
learned_something_new(TUT_SKILL_RAISE);
switch (skill)
{
// Special cases first.
case SK_FIGHTING:
mpr("Apart from making you more proficient in hand-to-hand combat, "
"Fighting also increases your maximum hitpoints.", MSGCH_TUTORIAL);
break;
case SK_ARMOUR:
mpr("Armour skill helps lessen the hinderance of heavy armour on "
"moving, spellcasting and other actions.", MSGCH_TUTORIAL);
break;
case SK_STEALTH:
mpr("By training stealth, you can make it less likely that monsters "
"will notice you. Note that monsters become more suspicious and "
"observant as you descend.", MSGCH_TUTORIAL);
break;
case SK_STABBING:
mpr("Stabbing is the skill that governs the likeliness of doing a "
"great amount of damage on a distracted or helpless creature. "
"Some gods may disapprove of this.", MSGCH_TUTORIAL);
break;
case SK_TRAPS_DOORS:
mpr("A character trained in Traps & Doors will be more observant to "
"his or her surroundings and be quicker in noticing traps and "
"secret doors.", MSGCH_TUTORIAL);
break;
case SK_UNARMED_COMBAT:
{
std::string text;
text = "A character trained in unarmed combat will occasionally do an "
"additional melee attack, provided they have the means to do "
"so.";
if (you.species == SP_MINOTAUR)
{
text += " For example, with your horns you can do a dangerous "
"headbutt attack.";
}
else if (you.species == SP_CENTAUR)
text += " For example, with your hooves you can kick your enemies.";
text += " Of course, this skill also trains your proficiency in "
"barehanded combat.";
mpr(text.c_str(), MSGCH_TUTORIAL);
break;
}
case SK_INVOCATIONS:
mpr("Your Invocations skill affects the likelihood trying to use a "
"divine ability will be successful.", MSGCH_TUTORIAL);
break;
case SK_EVOCATIONS:
mpr("Evocations is all about using magical items like wands, decks or "
"other objects. The higher your skill, the more likely is a "
"positive outcome when evoking items.", MSGCH_TUTORIAL);
break;
case SK_DODGING:
mpr("Obviously, the Dodging skill will affect your chance of dodging "
"an attack, be it melee, ranged, or magical. You cannot dodge "
"enchantments, sadly. You'll need magic resistance to resist them.",
MSGCH_TUTORIAL);
break;
case SK_SHIELDS:
mpr("A high Shields skill of blocking a melee or ranged attack with "
"your equipped (or a magical) shield.", MSGCH_TUTORIAL);
break;
case SK_THROWING:
mpr("Training Throwing will make thrown weapons (as opposed to ones "
"fired from a launcher) more effective. In particular, it makes "
"weapons of returning more likely to actually return to the "
"thrower.", MSGCH_TUTORIAL);
break;
case SK_SPELLCASTING:
{
std::string text;
text = "Now that you have the basic Spellcasting skill, you can learn "
"and cast spells, if you wish to. ";
if (you.religion == GOD_TROG)
text += "Note that Trog will disapprove of this, though.";
else
{
text += "In addition, gaining another level in Spellcasting will "
"occasionally grant your more magic and \"spell slots\" to "
"spend on new spells. A high Spellcasting skill will also "
"decrease the amount by which casting a high level spell "
"makes you hunger.";
}
mpr(text.c_str(), MSGCH_TUTORIAL);
break;
// Only one message for all magic skills (except Spellcasting).
case SK_CONJURATIONS:
case SK_ENCHANTMENTS:
case SK_SUMMONINGS:
case SK_NECROMANCY:
case SK_TRANSLOCATIONS:
case SK_TRANSMIGRATION:
case SK_DIVINATIONS:
case SK_FIRE_MAGIC:
case SK_ICE_MAGIC:
case SK_AIR_MAGIC:
case SK_EARTH_MAGIC:
case SK_POISON_MAGIC:
learned_something_new(TUT_GAINED_MAGICAL_SKILL);
break;
// Melee skills.
case SK_SHORT_BLADES:
case SK_LONG_BLADES:
case SK_AXES:
case SK_MACES_FLAILS:
case SK_POLEARMS:
case SK_STAVES:
learned_something_new(TUT_GAINED_MELEE_SKILL);
break;
// Ranged skills.
case SK_SLINGS:
case SK_BOWS:
case SK_CROSSBOWS:
case SK_DARTS:
learned_something_new(TUT_GAINED_RANGED_SKILL);
break;
default:
break;
}
"automatically. " EOL
"Once it is in your inventory, you can drop it again with "
"automatically. "
#ifdef USE_TILE
"(In Tiles, these will be marked with a green frame around them.)"
#endif
EOL "Once it is in your inventory, you can drop it again with "
// NOTE: This is called when a corpse is first seen, rather than
// first picked up, since a new player might not think to pick
// up a corpse.
// NOTE: This is called when a corpse is first seen as well as when
// first picked up, since a new player might not think to pick
// up a corpse.
break;
case TUT_GAINED_MAGICAL_SKILL:
text << "Being skilled in a magical \"school\" makes it easier to "
"learn and cast spells of this school. Many spells belong to "
"a combination of several schools, in which case the average "
"skill in these schools will decide on spellcasting success "
"and power.";
break;
case TUT_GAINED_MELEE_SKILL:
text << "Being skilled with a particular type of weapon will make it "
"easier to fight with all weapons of this type and make you "
"deal more damage with them. It is generally recommended to "
"concentrate your efforts on one or two weapon types to become "
"more powerful in them. Some weapons are closely related, and "
"being trained in one will ease training the other. This is "
"true for the following pairs: Short Blades/Long Blades, "
"Axes/Polearms, Polearms/Staves, Axes/Maces, and (though not "
"strictly a weapon skill) Slings/Throwing.";
break;
case TUT_GAINED_RANGED_SKILL:
text << "Being skilled in a particular type of ranged attack will let "
"you deal more damage when using the appropriate weapons. It "
"is usually best to concentrate on one type of ranged attack "
"(including spells), and to add another one as back-up.";
break;
case TUT_CHOOSE_STAT:
text << "Every third level you may choose what stat to invest in, "
"Strength, Dexterity, or Intelligence.\n"
"<w>Strength</w> influences the amount you can carry, and "
"increases the damage you deal in melee.\n"
"<w>Dexterity</w> increases your evasion and thus influences "
"your chance of dodging attacks or traps.\n"
"<w>Intelligence</w> increases your success in casting spells "
"and decreases the amount by which you hunger when you do so."
"\nNote that it is generally recommended to raise all your "
"stats to a minimum of 7, so as to prevent death by stat loss.";
"sometimes or always, hazardous. Only experience can help "
"you here.";
"sometimes or always, hazardous. You can find out whether "
"that might be the case by "
#ifdef USE_TILE
"clicking with your <w>right mouse button</w> onto the corpse "
"or chunk.";
#else
"<w>v</w>iewing a corpse or chunk on the floor or by having a "
"look at it in your <w>i</w>nventory.";
#endif
break;
case TUT_CAN_BERSERK:
// Don't print this information if the player already knows it.
if (!Options.tut_berserk_counter)
{
text << "Against particularly difficult foes, you should use your "
"Berserk <w>a</w>bility. Berserk will last longer if you "
"kill a lot of monsters.";
}
text << "You just gained a new ability. Press <w>a</w> to "
"take a look at your abilities or to use one of them.";
text << "You just gained a new ability. Press <w>a</w> to "
"take a look at your abilities or to use one of them.";
text << "You just gained a new ability. Press <w>^</w> to "
"take a look at your ability.";
text << "You just gained a new ability. Press <w>^</w> "
#ifdef USE_TILE
"or press <w>Shift</w> and <w>right-click</w> on the "
"player tile "
#endif
"to take a look at your abilities.";
// Piety decreases over time for non-good gods
text << ", not doing things to please him frequently enough, or "
"a combination of the two";
// Piety decreases over time for non-good gods.
text << ", because " << god_name(you.religion) << " finds your "
"worship lacking, or a combination of the two";
text << "If your piety goes to zero, then you'll be excommunicated. "
"Better get cracking on raising your piety, and/or stop "
"annoying your god.";
text << "In any case, you'd better reread the religious description. "
"To do so, "
#ifdef USE_TILE
"press <w>Shift</w> and <w>right-click</w> on your avatar.";
#else
"type <w>^</w>.";
#endif
"to nothing). Maybe you repeatedly annoyed him, "
"or maybe you weren't doing things that pleased him "
"often enough, or some combination of the two. If you "
"can find an altar dedicated to " << old_god;
"to nothing). Maybe you repeatedly violated the "
"religious rules, or maybe you failed to please your "
"deity often enough, or some combination of the two. "
"If you can find an altar dedicated to "
<< old_god_name;
text << "If you decide that abandoning " << old_god << "wasn't "
"such a smart move after all, and you'd like to return "
"to your old faith you'll have to find an altar "
"dedicated to " << old_god << " where";
text << "Should you decide that abandoning " << old_god_name
<< "wasn't such a smart move after all, and you'd like to "
"return to your old faith you'll have to find an altar "
"dedicated to " << old_god_name << " where";
text << "Fortunately, it seems that " << old_god << " didn't "
"mind you converting to " << new_god << ". This "
"is only the case when converting from one of the "
"three good gods to a different good god, so don't "
"expect this to be the norm.";
if (is_good_god(new_god))
{
text << "Fortunately, it seems that " << old_god_name <<
" didn't mind you converting to " << new_god_name
<< ". ";
if (old_piety > 30)
text << "You even kept some of your piety! ";
text << "Note that this kind of alliance only exists "
"between the three good gods, so don't expect this "
"to be the norm.";
}
else if (!god_hates_your_god(old_god))
{
text << "Fortunately, it seems that " << old_god_name <<
" didn't mind you converting to " << new_god_name
<< ". That's because " << old_god_name << " is one of "
"the good gods who generally are rather forgiving "
"about change of faith - unless you switch over to "
"the path of evil, in which case their retribution "
"can be nasty indeed!";
}
else
{
text << "Looks like " << old_god_name << " didn't "
"appreciate you converting to " << new_god_name
<< "! But really, changing from one of the good gods "
"to an evil one, what did you expect!? For any god "
"not on the opposing side of the faith, "
<< old_god_name << " would have been much more "
"forgiving. ";
angry = true;
}
text << "Looks like " << old_god << " didn't appreciate you "
"converting to " << new_god << "! (It's only safe to "
"convert between the three good gods.) Unfortunately, "
"converting back to " << old_god << " will annoy "
<< new_god << ", so you're stuck with having to suffer "
"the wrath of one god or another.";
text << "Looks like " << old_god_name << " didn't appreciate "
"you converting to " << new_god_name << "! (Actually, "
"only the three good gods will sometimes be forgiving "
"about this kind of faithlessness.) ";
angry = true;
}
if (angry)
{
text << "Unfortunately, while converting back would appease "
<< old_god_name << ", it would annoy " << new_god_name
<< ", so you're stuck with having to suffer the wrath of "
"one god or another.";
text << "You can increase your chances of survival until you can find "
"the exit (a flickering <w>\\</w>), keep moving, don't fight "
"any of the monsters, and don't bother picking up any items "
"on the ground. If you're encumbered or overburdened then "
"lighten up your load, and if the monsters are closing in, try "
"to use items of speed to get away. And where possible, move "
"in a direction slightly off from a compass direction (for "
"example, north-by-northwest instead of north or northwest), "
"as you'll likely miss the exit if you keep heading solely "
"in a compass direction.";
text << "To increase your chances of survival until you can find the "
"exit"
#ifndef USE_TILE
" (a flickering <w>\\</w>)"
#endif
", keep moving, don't fight any of the monsters, and don't "
"bother picking up any items on the ground. If you're "
"encumbered or overburdened then lighten up your load, and if "
"the monsters are closing in, try to use items of speed to get "
"away. Also, wherever possible, move in a direction slightly "
"off from a compass direction (for example, north-by-northwest "
"instead of north or northwest), as you're more likely to miss "
"the exit if you keep heading solely in a compass direction.";
case TUT_YOU_RESIST:
text << "There are many dangers in Crawl. Luckily, there are ways to "
"(at least partially) resist some of them, if you are "
"fortunate enough to find them. There are two basic variants "
"of resistances: the innate magic resistance that depends on "
"your species, grows with the experience level, and protects "
"against hostile enchantments; and the specific resistances "
"against certain types of magic and also other effects, e.g. "
"fire or draining.\n"
"You can find items in the dungeon or gain mutations that will "
"increase (or lower) one or more of your resistances. To view "
"your current set of resistances, "
#ifdef USE_TILE
"<w>right-click</w> on the player avatar.";
#else
"press <w>%%</w>.";
#endif
break;
case TUT_CAUGHT_IN_NET:
text << "While you are held in a net, you cannot move around or engage "
"monsters in combat. Instead, any movement you take is counted "
"as an attempt to struggle free from the net. With a wielded "
"bladed weapon you will be able to cut the net faster";
if (Options.tutorial_type == TUT_BERSERK_CHAR)
text << ", especially if you're berserking while doing so";
text << ". Small races may also wriggle out of a net, only damaging it "
"a bit, so as to then <w>f</w>ire it at a monster.";
if (Options.tutorial_type == TUT_MAGIC_CHAR)
text << " Note that casting spells is still very much possible.";
break;
case TUT_LOAD_SAVED_GAME:
{
text << "Welcome back! If it's been a while since you last played this "
"character, you should take some time to refresh your memory "
"of your character's progress. It is recommended to at least "
"have a look through your <w>i</w>nventory, but you should "
"also check ";
std::vector<std::string> listed;
if (!your_talents(false).empty())
listed.push_back("your <w>a</w>bilities");
if (Options.tutorial_type != TUT_MAGIC_CHAR || how_mutated())
listed.push_back("your set of mutations (<w>A</w>)");
if (you.religion != GOD_NO_GOD)
listed.push_back("your religious standing (<w>^</w>)");
listed.push_back("the character overview screen (<w>%</w>).");
text << comma_separated_line(listed.begin(), listed.end(),
" and ", ", ");
text << "\nAlternatively, you can dump all information pertaining to "
"your character into a text file with the <w>#</w> command. "
"You can then find said file in the <w>/morgue</w> folder ("
<< you.your_name << ".txt) and read it at your leasure. Also, "
"such a file will automatically be created upon death (the "
"filename will then also contain the date) but that won't be "
"of much use to you now.";
break;
}
text <<
"<w>Renounce Religion</w> will make your character leave your god" EOL
"(and usually anger said god)";
if (you.religion == GOD_TROG)
{
text << ", while <w>Berserk</w> temporarily increases your" EOL
"damage output in melee fights";
}
text << ".";
text <<
"<w>Renounce Religion</w> will make your character leave your god" EOL
"(and usually anger said god)";
if (you.religion == GOD_TROG)
{
text << ", while <w>Berserk</w> temporarily increases your" EOL
"damage output in melee fights";
}
text << ".";
if (Options.tutorial_type == TUT_MAGIC_CHAR
&& !is_light_armour(item))
{
ostr << "\nNote that body armour with high evasion penalties "
"may hinder your ability to learn and cast spells. "
"Light armour such as robes, leather armour or any "
"elven armour will be generally safe for any aspiring "
"spellcaster.";
}
else if (Options.tutorial_type == TUT_RANGER_CHAR
&& is_shield(item))
{
ostr << "\nNote that wearing a shield will greatly decrease "
"the speed at which you can shoot arrows.";
}
"<w>d</w>rop menu. On a related note, offering several "
"corpses on a floor square is facilitated by using the "
"<w>c</w>hop prompt where <w>c</w> is a valid synonym "
"for <w>y</w>es or you can directly chop <w>a</w>ll "
"corpses.";
"<w>d</w>rop menu. On a related note, butchering "
"several corpses on a floor square is facilitated by "
"using the <w>c</w>hop prompt where <w>c</w> is a "
"valid synonym for <w>y</w>es or you can directly chop "
"<w>a</w>ll corpses.";
// 8 is the default value for the note-taking of OOD monsters.
int level_diff = mons_level(mons->type) - (you.your_level + 8);
// 8 is the default value for the note-taking of OOD monsters.
// Since I'm too lazy to come up with any measurement of my own
// I'll simply reuse that one.
int level_diff = mons_level(mons->type) - (you.your_level + 8);
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 (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";
dangerous = true;
}
"you in battle.";
"you in battle. You can order your allies by <w>t</w>alking "
"to them.";
}
else if (dangerous)
{
if (!Options.tut_explored && mons->foe != MHITYOU)
{
ostr << "You can easily mark its square as dangerous to avoid "
"accidentally entering into its field of view when using "
"auto-explore or auto-travel. To do so, enter the level "
"map with <w>X</w> and then press <w>Ctrl-X</w> when your "
"cursor is hovering over the monster's grid. Doing so will "
"mark this grid and all surrounding ones within a radius "
"of 8 as \"excluded\" ones that explore or travel modus "
"won't enter.\n";
#ifdef USE_TILE
ostr << "Upon returning to the main map, you'll even find all "
"surrounding grids visibly highlighted.";
#endif
}
else
{
ostr << "This might be a good time to run away";
if (you.religion == GOD_TROG && !you.duration[DUR_BERSERKER]
&& !you.duration[DUR_EXHAUSTED]
&& you.hunger_state >= HS_SATIATED)
{
ostr << " or apply your Berserk <w>a</w>bility";
}
ostr << ".";
}
// in the previous round of a given distance. We use an array of size 2,
// so we can comfortably switch between the list of points to be
// investigated this round and the slowly growing list of points to be
// inspected next round. Once we've finished with the current round, i.e.
// there are no more points to be looked at in the current array, we switch
// circ_index over to !circ_index (between 0 and 1), so the "next round"
// becomes the current one, and the old points can be overwritten with
// newer ones. Since we count the number of points for next round in
// next_iter_points, we don't even need to reset the array.
// in the previous round of a given distance. Because we check all grids of
// a certain distance from the starting point in one round, and move
// outwards in concentric circles, this is an implementation of Dijkstra.
// We use an array of size 2, so we can comfortably switch between the list
// of points to be investigated this round and the slowly growing list of
// points to be inspected next round. Once we've finished with the current
// round, i.e. there are no more points to be looked at in the current
// array, we switch circ_index over to !circ_index (between 0 and 1), so
// the "next round" becomes the current one, and the old points can be
// overwritten with newer ones. Since we count the number of points for
// next round in next_iter_points, we don't even need to reset the array.
return (item_type_known(item)
&& (is_good_god(you.religion) && is_evil_item(item)
|| you.religion == GOD_TROG && item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& item.sub_type != BOOK_DESTRUCTION));
if (you.religion == GOD_TROG)
{
return (item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& (!item_type_known(item)
|| item.sub_type != BOOK_DESTRUCTION));
}
return (is_good_god(you.religion) && is_evil_item(item)
&& item_type_known(item));
rarity += book_rarity(mitm[i].sub_type);
// Piety increases by 2 for books never picked up, else by 1.
if (mitm[i].flags & ISFLAG_DROPPED
|| mitm[i].flags & ISFLAG_THROWN)
{
totalpiety++;
}
else
totalpiety += 2;
rarity += book_rarity(mitm[i].sub_type);
// Piety increases by 2 for books never cracked open, else 1.
// Conversely, rarity influences the duration of the pyre.
if (!item_type_known(mitm[i]))
totalpiety += 2;
else
totalpiety++;
if (count)
{
if ( cloud != EMPTY_CLOUD )
{
// reinforce the cloud
mpr( "The fire roars with new energy!" );
const int extra_dur = count + random2(rarity/2);
env.cloud[cloud].decay += extra_dur * 5;
env.cloud[cloud].whose = KC_YOU;
continue;
}
if (count)
{
if (cloud != EMPTY_CLOUD)
{
// Reinforce the cloud.
mpr( "The fire roars with new energy!" );
const int extra_dur = count + random2(rarity/2);
env.cloud[cloud].decay += extra_dur * 5;
env.cloud[cloud].whose = KC_YOU;
continue;
}
// to the flavourness of bees finding their way
// back to the Hive (patrolling should really be
// restricted to cases like this), and for the
// other part it's not that important because
// to the flavour in e.g. bees finding their way
// back to the Hive (and patrolling should really
// be restricted to cases like this), and for the
// other part it's not all that important because
// can only just see the next one. Note that grid_see_grid() is probably
// rather too conservative in these estimates.
// This is done because Crawl's path finding once a target can be seen is
// very robust and because it allows for more natural traversing if there are
// other monsters in the way.
// can see (and, more importantly, reach) the next one. Note that
// grid_see_grid() is probably rather too conservative in these estimates.
// This is done because Crawl's pathfinding once a target is in sight and easy
// reach is both very robust and natural, especially if we want to flexibly
// avoid plants and other monsters in the way.
else
{
// Make the name before we curse it.
do_curse_item( you.inv[you.equip[affected]], false );
}
// Make the name before we curse it.
do_curse_item( you.inv[you.equip[affected]], false );
learned_something_new(TUT_YOU_CURSED);
mpr(" s - Order allies to stop attacking");
mpr(" w - Order allies to wait here");
mpr(" f - Order allies to follow you");
mprf("Orders for allies: a - Attack new target.%s", previous.c_str());
mpr( " s - Stop attacking.");
mpr( " w - Wait here. f - Follow me.");
if (wielded != -1)
{
if (_recharge_rod( you.inv[wielded], true ))
return ;
}
if (wielded != -1 && _recharge_rod( you.inv[wielded], true ))
return;
// He, we don't want those "Whew, it's safe to rest now" messages when
// you were just cast into the Abyss. Right?
if (player_feels_safe && you.level_type != LEVEL_ABYSS)
if (Options.tutorial_left)
if (Options.tutorial_left)
Options.tut_just_triggered = false;
if (you.attribute[ATTR_HELD])
{
learned_something_new(TUT_CAUGHT_IN_NET);
}
// We don't want those "Whew, it's safe to rest now" messages when
// you were just cast into the Abyss. Right?
else if (player_feels_safe && you.level_type != LEVEL_ABYSS)
if (Options.tutorial_type == TUT_MAGIC_CHAR && you.magic_points < 1)
learned_something_new(TUT_RETREAT_CASTER);
if (Options.tutorial_type == TUT_MAGIC_CHAR && you.magic_points < 1)
learned_something_new(TUT_RETREAT_CASTER);
}