crawl_environment, player and monsters classes have been left in externs.h, which necessitates that all of the enums references by those classes stay in enums.h, since you can't forward declare an enum. However, it's a start.
Also, portions of misc.{cc,h} have been split off into traps.{cc,h}, place.{cc,h} and terrain.{cc,h}
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2095 c06c8d41-db1a-0410-9941-cceddc491573
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
FZMSMMN7OGVWVBMT45TW5ETLSKCLIYBB3BGKGQ3NZJSVE25IGYNAC
B3SINXBL7IW6267A4EKUWL5T2SZKIPJVC2DQR2DZMJRNYNW6LV3QC
RZLMIEOHITWGYNVBHDVVWS24YQ5SD5HG3T3JCMIBCD2VA5TEPHCQC
KPPLEKBFBHSSS6UCYPCPNRZ3ONXFHHLX3GZJBINEZFQJ55LC2LMAC
PL3PET5GVBU4DI5K34RTLMOG2374FQHBMSDR4ZASNTECWPQ4YPRAC
LVP5I5DHJGY3DG3DLIYBDVNULBCM7CD3HF4E5DW5QHCM6P2UZEJQC
ORDJOZ5AKTVNOGJUURTXBPAVOBOTRR3R4IIM7X2TSWGNVFHEC53QC
SCZCQPNBQG2GXZ76LCEYOMB4QMZGI6YV7LJEC7ZVBUG27KLO564AC
C5VA63WAQRWPENIMXRPUPZLZJMC77PL2B3A77HYFWDCZU5QDG7VQC
LUNOTEIMYZJ7JL5P55GEHUVSDEZMYX3TWYUB2ABRHAYJEWQSSXIAC
XEC3L6W6TGIRWHINULNLKCIP4UBMHFYE33WJL7272I2GRRCFZBWAC
6ZZO2QBB46RZM6OXVS7OIKC5M3SEAULSSJFXW5PJG556JDKKUHWAC
OHJE4HQ2B3HVV4BOPBRFKO6HBRTLZEI74P5PLJF5GLSRD2MFWXHQC
NXJMKEIPL2MMQEQVXQCZOQWPQ767WS5ZP5CKDAENJFFDB3N4NDNAC
WC3PNJUPYSMCYWOETNBJVOFXH5S6ZED4XXJBSF54V7P3HZYVO5KAC
L4RYVF46EQKMVOEADGRG4WMPVTQ6NNFGYMU4SHAH6XJIKWVHT77QC
6OPWKN5LKYBZQLD25BGC4T3P5KXCJM6KNLOEQCPMLKYPY3UATKEQC
P2YNOE2TUTZFAOBTHJOIVD6TCV7J7D2UKUX67LHZUL6QY44ZMENQC
DS2GZKISEP2DM2VU6EJ525Q7W3WVOKJXG5PY2OY4VNFCLBHVVOTAC
UH3CJQMQ3NPICXD34NTCTUZJWOCEF4P5XEGXFLLNDDFLZK7QPUBQC
45MYNXZEG5E2GIOGVN2JXQFLHC56WTCXPD2SW6S6LZJ643G24JHQC
BJPPSWEN35BG4KP3XTXPDMAJ2GAUMHXKHCNALAZ4B4OS6B3KDSUQC
L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC
SEXTAB43OKE5D5NNPNNPJXWR3CLJVRL7VSLMKDATDRLNX4FI3AFQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC
HYS3HXTXATFPN7GLN3WBGDCP22UT2D3JBVUS7SP5FE7L54TDCJRQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
547JREUJXTZNYVGHNNAET5F5O5JYYGNTDQB6ABZNT7YX5EY64OHAC
5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
4EZVKDQA5GM3QDTNTCKEKGH4F6LGAYNLBT756PXODKZ2B7C4ZVHAC
BXXOYFMWNQY4TLLJBFYROSH43KO5F4JQTATU3ZEJNKGIJGOIQN4AC
T4IH76FA5TWHFOZUJFHLQXQJENJHWTUZZP4EGNA7D4GTZY7D4ZKAC
ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC
GACH6PWPGGUBEE7PFEPQMOZKSR7HTQGL2WLGF2AQPJD3FCCSKZNQC
DDU4A3JGN5IUIPP5IASOODKPR2WBHSDSV4FITZ6HNXNSXXQACWAQC
W4LFYTIOCEWMSU45KP2YAVH7PCTGHTM7LUCGZNEEHW2WL43FZBKQC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
UURAYLSSITZLQR56MCWFPIWMECU7F3USMA2UPJAO4IPIY5WVKP5QC
5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC
43ZTEB57FU7KE5EVMYWZONNVJBZCGF3JEAJZIY25LC4LGE65PG5QC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
TR4NPGNO5QNNRJNVMNSUEO5QLT37HCXXDOBKXCB5XWXRQNAJ5SHAC
4XGOVPFCU6KZIYHKWCHUTZY6G5S326DKBG3UREPR34Q4TSDD3TAAC
IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC
LAMIVDKY7LO5ONX5Z273ZCCEA5UBENOJD5VWNE4AK2EXGFED6BFQC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC
NOB3FIJ2IOGBSK3EKCRS2WORSMTFPFKOQL4V7BTBLENYYTBUPHQQC
GBUB77EAYHOFY6GQ5IY3ZSBC7FSQFZZKYNBD5QMCQFIKFLYLWHOQC
ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC
BRGAZR5AXWC2IALBVXO5SB354IRQEIRHSK55RZPGFI4AGIOD4LUQC
X76YXE6RFL7QY5WL6MSSS44WHVA5FQMDQY3XTYP2UL6UZB4E6XMQC
557IY36VX2M4ERVCP5HNI3YTHHVTHPETZ5RWDX5BKDKXXIYCFUJAC
2WRXQTGYDBLV46WRNVIUKGNA5QS563XZNNW3N2L6PVOCHIP2YGHQC
GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
XVX7AVLLYZJIJUZA2LZ6T57PHULWPDRZOHELDF4JHZ35EMINFFZQC
SCWXQW5H65OXUP2MEJ2MEEAVPSRJDT3RQGKYCMKVTORS2334PQSQC
UDYVF65OZSNPANLHDI3ODBEGUAKAVZ4KH4OZFAKR2CQJPO4AXU6QC
7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC
LDGIQP4A5BWVFQWQ2MGZRM5OY45ZXNNARH4WZPLUTBJVS4CVHISQC
UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC
ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC
6HG6JFO47Y3BZLU7Y6G3R2CX6JFGN4X5PKK6S5IGUXUYQ5GVZYFQC
KXUQB3WNWC5IFL6VFWADEPQMMU3VV3NDI5FLA666PGOEWFYUHCLQC
GRH4XPIYHDOXXF3R3QPMZTFHGLO2OJAZS4FLNBBXG3DHTQQM7RDQC
7VVRO5HMNNOXVRLBLJUCHUJP6MDIRMC2BWCO7MWH4OLQRM3LMTMQC
UWMN4HLG6YA2YFQEVIVMDISD6APKEPIZXMMPMNUYCBQDSAUYSXPQC
BPSH3LUDUTXMK2QZKSMFDTBNDD6HPILMCBLZNMCRLZZQKPS5QOQQC
VNHFP63ZLLZU3A3PLXP4BITX57DUIYDHFOHQYK3BOBHV3S64G26QC
PJDC24L7LXX6NZ7J5P7MNJJHAKQDJQEBV4CMDR4VSXLMWRIBMNKQC
5KJCHLIUFKRPMIVWUAYT6EOF7SW4PTQF6Y5OPEFWXGLE7DUGYLZAC
TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC
YQ5IYBHW2ICYKOC2M6CI5BNOZKST3DIMMZRQN72LUQCHDAPVYQCQC
LOJYD6QZRNLNDDZJKVBMKQIBPTKSRN2ETCYGNVV47M7L3QLUJUJAC
WHY6LRRJ5T2NSBE3IUCR4X3TOAH7TTK5NPUPUIFT7TPNJ6J4HBDAC
ZJU5Z2WDMI7HN4XJ3NVTVRHIZO2CGFUQ2FSKIRJVTQG47XHNCZFQC
7X4EXGVZZP5RSNEWTE6MRLGGC4KJT45AQUKQ4VSNYWT3C7TQSLBAC
AFE345BJ7IX2YYYX3I5I6RYLXNWJCFE4WMH6F5JMIR6X7WUP75CAC
RGY2525RQH7SSGM6ZVI7CZL4WMNFZK2WRABOSIWRKQYYOU2RWN4QC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
ESWIM76FGJL4QFLSHU6AC4D74PT7OPLQ7ZCJYWLZS5UCBAJDXYHAC
JWOMWPRTOIUVAA3TLIGSB4HVFINNUDTKO2TKVAUCXE26G3KTKYOAC
I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC
6KCWO7XCDBGOYSUWVEXC74XC6RZ7ZJQLLSES5IIPCTILTECYMFZAC
PKR7JPAXDEL6NSRX5OO45BXOMJL7IQ3L4JV4O5CF2DQJFBEC2NJAC
RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC
Y66ZAXN24E3HLIBOSW4OXUTQ4X4PRGNJII4KVDQH4GQJVA6GO3NAC
WCK6TM2ZD56WSOK6SMMKBYAYGG4OUCTILLMVVLMB4QO5I5S2IVNAC
ID2OZJTHFXL74RVUCS3JCMDQEUHAXCQFZU7235VU6IEVAAUWD2FAC
6HQB2N6N75R2RGKJFWRUN7WAC2PNGWQFXTII5DTRLTHZ2BOTMTVAC
KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC
ANBVGN4RZOMY5LI4QSHOV2477FN55H353ZYLSVCPTXC7AWWSQZBAC
NCDWWDJQLAU5ORSAQGZKJJ5E22VTDGGPJMVVBWQFHQ2B3U3UFHDQC
JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC
JTTHP2BEYEPBQMSDM7IKANTMKRPY6ACGL2JN4D3OBZ7HFXKAYEGQC
OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC
RGHXFBNIULRVRYLBGG5JZDMYVM2E2JJ2Y5KQPMU6PUS3V26G6ZXQC
UB73UGG2GEG6AL4T76UILFLTELH4Z5WN54UROLJD6RDR3JG77CXAC
YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC
W6IY6LF3MREPXC23AAKA2BJNUCJYCSOWY55DIWJWFLUEE2Y3LGNQC
34C4U6EQWERY75GZJKUCM5KVGU2OUICETS5LGZF6RMKMZT4R5SQAC
JVSCP4FTW2G57C6YD5HZOZXTODGZH7TR75JQGFJBEPX3LCZH236QC
RR2J4VLJCZSAKY3HNS334KI4YUAPOMSETO2HGCGEEIUCUJAYAGSQC
3KAINFIXO7WNWGUGZB43EUNFRS2ZPBLQZDTY456QACMRHYIJ7WDAC
H7BW6SEIQ57X6V4BM2RX54W42W6BH5XJBAS6FYCYKLQQG43ZMU4QC
2KTJHQUX2LTU2BCLS5YXVRRKMOYKKIZAPF2LBKORFGSHEN5IO3IAC
2ESKXYN266CEMLSL6DNCKG4REDO34FXL4ODVGMWDJTNJRKMXWCRQC
JYCMD6WMNHXA53K4LLKVTNX6PLRLU25F6J2TYMPQXM2ENAE66NIAC
X6JIHUW4GZTWTNA7U6TTHRO4P2I7GNSS7TQDPQWVTIHBIG4NVWXQC
6GDKXNFXPKQ6AVNOSMJECN7CLELM2KCMVRM2A7BARLK2NNILN6SAC
YATODO2EN3AW7IXW5PL25HHK34YHF6Y32QBMOUZXEATZZ4YQQWZQC
BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC
K2MLPJIAXXZRWEWZCNSGICCBNIU2WAAPT7SPIMOH7FLLTOB4QFRAC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
LEY3EZGTCBV6CYX4L727KQ4ZXL2LZLT5WESN3WAF65VRMX4EDP4QC
ITQ2EXDFLN3EHCURKYHZYVWFACD4KW7NA6CMHNKGWTDKHCHQAE6AC
VD4KDTGHVKCN35AWREYB4TEOUMCTW7SAUPAMTMF5ABC7VBHVKP4AC
GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
B3MFLKPJ34I2USQX7UM3SPDIFVGACB5HXYLEKT3FDULL57QOE2LAC
AOAJ6D3OKSELEYKAT55XCVU5LYJ7SMCZKC6DIEGLLB3TF2LEENWQC
YOH32TMLN6QJG4ZFLYWPJF3YUEGIMZPVPYN57RTB26QBBHMICV3AC
CIPVRZGLOZHCERK6YPOBV3P2E4IAB4H6D5EHLRQE2O5E4P4VCBUAC
NEECVIIAOBP72T6O44DWAA6HFSDY3KSWYCFMKAEMDMVOI7XASD7QC
3JOOHBLF6D4362LD2TQGKYB5JVTNX34DD7DPXVJL5E2K2QN2EFLQC
WLX2RQMMOMP2PYPAGJRM4VFD2WTLJTOAZZPPY3MV76FU2EGEJ54QC
PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC
CVC5FFFLGVRR3KPYDNB6RF4FNACV3LI3HPSR4MCUNZ4C3FSQYBDAC
OWNMHNCGA5H3A6AULXXW473PKC7N6IINE3LJCB3KCFG2XA3TYCQQC
QXQE7C5XDYNF4JSHGDAVMS7HYLOC6YEZFOVFJ3RD7RB6U4AJSFIQC
Z3RI4XAN7J2GUABAQ5G6YIOQYMBOAEQFFGRBWHMUEB2A2QYXO5MQC
GSQ72ULBSL6WBJZUB3GJKAPQDXZIQV7B2TDBA5OP2WVGHVJMCQFQC
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
JW2KRJHES33W7UTWZ6NDO4TLMK4EFU4HKZXBWR2UJOMPCCOTR4CQC
YHSVOROKPYS33Y4RYZRVZTE3G5LXOFX52HEDNLV6HIXOJYNOKH3QC
KW43PGXTTM57DXUGGBQXJ5G5OYYIY3WB76TXIKL2ZCIJGH7GH4LAC
VIFRP3HZEONFR6PQRYZYM3YUEJOQ7T4F5CZY4MN4YJMB23FMU7XAC
6GSPAIEMWJXYSCR5EC2WBOGYDEDR6ESIZC6TKN2FVE2CVPSHUHXAC
DH3YTI6VVI727SQXO4CXSDCSBG2UN3UAWLFULBGRLBVH22ACRXIAC
4HATGRJJE7Q6LXHJ3ZGYTNBLG542KAUEK6ERKARIYRKRWY6VTDKQC
4GFCF6N3MZSCHUB77Z3SQYJ3FYR5N3VBW2CGWANLJ74O5FEQH3CQC
3BYA46OYLVN6ZPGAZD5OGIMMH5PRWGNSU3ITJRCVBE6P5HYYYAYQC
34RCM6RXIWHZMYXNGFQKLKQIAJ6QISIQ3D5HMK4HZNLVX66BSUBAC
6LT6USGJOTDMRJGXLAN2NSZXK2GKWEXDKKUV6SVV7ZC6WI6EKMDQC
CQ24AVAI6SW3AHTIDMLPSTRRBEU6FHRF5I5FD6G5QIYE6PO4BQMQC
IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC
XPCGZBHHSL6MB3ORMUJI64BAERU6AZTIY6RK56BBW7SNB3IK24IAC
6ME4TYV7ITXCAUMNVB27LRRHB72J2FVVZMJNS34IMAN57R37AE2QC
NZFU5APXZZDBRYJGE57F43JKBBPWC33TIZNK6K4OZYSI47PFJMQQC
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
HH3HFWVXABJ4IRMN22PPJCREMULZSN6DA7VYKOGECGMNUQTZ5QNQC
33ZMPQC6OXTESW7SRW765GRNJUEJRSYONRVZVIEUDAUEJ2PPMB4AC
4Q5OYUKF2SGF7WHMIVYFZVXXDCFUCYY534VLOGKWYRSPYKRXMVDAC
4DOLKETM4WHB5JUNXNBZJJKMJSMABCQOFPMKREE5VCQHRUEDR3MAC
L4PKJZERR7WADKWHY3MR6J6OZFREVPL3CB43I6MLJ2BVKWCUTE7AC
OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC
PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC
XS4OT3JJKMXJIOMIGSSHIE4IOV2EXKFFELHEU7J2C2B7PKAP4V4QC
P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC
JK3HFJG76OOQHJMXJUSZRTR5CX5ZMS52LRVBLOR7E2NBI6PRSHHAC
TCB6NKWD6VFEKM43J3ZIJJPRL7M4PRNWTELT4G2XWI4EMUDZIZLQC
WWR4IDWLXP4XLBWDZBA5GFG7CRKUJQNRK7FFUFOISK6OJTMYQPFQC
TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
6NTCURCJQA4PBNDD5VGFBQAF5QCZZPLWRDZTA65R3EOGMVA475IAC
FA2V3G4NYTWJWUT7EWH75L3YOUX6YVOZ5LNRSFLO2XF273JKSUTAC
7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC
YAAJ6PTN6QUSWE52URI5AENOGD366FIHOIFUOXFUJLVZYE4OG6HQC
IHIJSWVOONSTA2WCHKW3YKBLETUQECFVBVLMET5SGQZ4C6U3GCUQC
LBIXGRQC64MEHG7L74PCGU3EXD3WVUCDR7DHEHCI5OCOJAXSA7PQC
P722Q43MJLCJ5NHF6FA27YM7IYP2ZTP6WP373BAVZPODZW4JLJPQC
FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC
RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC
HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC
WT66JDIRTLLP37SHTV4GI3V64JFJ4D25LNRLGCHFG6CLEFKJ3QGQC
2BTN774TDEFKS7L23YNEDQJSLSUWWKXPC5GA73ZGKLCKDHVEWSJAC
KFZYPFHHOWRUZEK2PW26EI73Z6I6DLHW2YEJV2CB5XBWFRRNBFXQC
ZHFUXYUHS6V47WK2NRH7OU6RX77NRKTXOZC3MND2GG7PEEWSGFTAC
FMBJCM5LJKCG326YRJGOOJU6QNWONXAHK2AB4CP4SAOHKJ5CORXQC
PTB7I4WQ3NTF7BE3O6WKXDSJD6QRWSZIEWPBSZGCJJZVNKT4OL5AC
7PRZJ6KZLG26YVTAMXT7YOTQLWZHGWGRTKXZZ52P4XYCQD4GT5WQC
// various elemental colour schemes... used for abstracting random short lists
// MUST match the order in initfile.cc or breakage results.
enum element_type
{
EC_FIRE = 32, // fiery colours (must be first and > highest colour)
EC_ICE, // icy colours
EC_EARTH, // earthy colours
EC_ELECTRICITY, // electrical side of air
EC_AIR, // non-electric and general air magic
EC_POISON, // used only for venom mage and stalker stuff
EC_WATER, // used only for the elemental
EC_MAGIC, // general magical effect
EC_MUTAGENIC, // transmute, poly, radiation effects
EC_WARP, // teleportation and anything similar
EC_ENCHANT, // magical enhancements
EC_HEAL, // holy healing (not necromantic stuff)
EC_HOLY, // general "good" god effects
EC_DARK, // darkness
EC_DEATH, // currently only assassin (and equal to EC_NECRO)
EC_NECRO, // necromancy stuff
EC_UNHOLY, // demonology stuff
EC_VEHUMET, // vehumet's odd-ball colours
EC_BEOGH, // Beogh altar colours
EC_CRYSTAL, // colours of crystal
EC_BLOOD, // colours of blood
EC_SMOKE, // colours of smoke
EC_SLIME, // colours of slime
EC_JEWEL, // colourful
EC_ELVEN, // used for colouring elf fabric items
EC_DWARVEN, // used for colouring dwarf fabric items
EC_ORCISH, // used for colouring orc fabric items
EC_GILA, // gila monster colours
EC_FLOOR, // colour of the area's floor
EC_ROCK, // colour of the area's rock
EC_STONE, // colour of the area's stone
EC_MIST, // colour of mist
EC_SHIMMER_BLUE, // shimmering colours of blue.
EC_RANDOM // any colour (except BLACK)
};
enum run_check_type
{
RCHECK_LEFT,
RCHECK_FRONT,
RCHECK_RIGHT
};
enum run_dir_type
{
RDIR_UP = 0,
RDIR_UP_RIGHT,
RDIR_RIGHT,
RDIR_DOWN_RIGHT,
RDIR_DOWN,
RDIR_DOWN_LEFT,
RDIR_LEFT,
RDIR_UP_LEFT,
RDIR_REST
};
enum run_mode_type
{
RMODE_INTERLEVEL = -4, // Interlevel travel (Ctrl+G)
RMODE_EXPLORE_GREEDY = -3, // Explore + grab items (Tab/Ctrl+I)
RMODE_EXPLORE = -2, // Exploring (Ctrl+O)
RMODE_TRAVEL = -1, // Classic or Plain Old travel
RMODE_NOT_RUNNING = 0, // must remain equal to 0
RMODE_CONTINUE,
RMODE_START,
RMODE_REST_DURATION = 100
};
/*
* File: traps.h
* Summary: Traps related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.h
*/
#ifndef TRAPS_H
#define TRAPS_H
#include "enum.h"
struct dist;
struct bolt;
class monsters;
bool trap_item(object_class_type base_type, char sub_type,
char beam_x, char beam_y);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
void disarm_trap(struct dist &disa);
void remove_net_from( monsters *mon );
void free_self_from_net( bool damage_net = true );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr - misc
* *********************************************************************** */
void handle_traps(char trt, int i, bool trap_known);
int get_trapping_net(int x, int y, bool trapped = true);
void mark_net_trapping(int x, int y);
void monster_caught_in_net(monsters *mon, bolt &pbolt);
void player_caught_in_net(void);
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: misc - mstuff2
* *********************************************************************** */
void itrap(struct bolt &pbolt, int trapped);
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells3
* *********************************************************************** */
int trap_at_xy(int which_x, int which_y);
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells2 - spells3
* *********************************************************************** */
dungeon_feature_type trap_category(trap_type type);
int trap_at_xy(int x, int y);
trap_type trap_type_at_xy(int x, int y);
#endif
/*
* File: traps.cc
* Summary: Traps related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.cc
*/
#include "externs.h"
#include "traps.h"
#include "beam.h"
#include "direct.h"
#include "it_use2.h"
#include "items.h"
#include "itemprop.h"
#include "makeitem.h"
#include "mon-util.h"
#include "monstuff.h"
#include "ouch.h"
#include "player.h"
#include "randart.h"
#include "skills.h"
#include "spells3.h"
#include "spl-cast.h"
#include "spl-util.h"
#include "terrain.h"
#include "tutorial.h"
#include "view.h"
static void dart_trap(bool trap_known, int trapped, bolt &pbolt, bool poison);
// returns the number of a net on a given square
// if trapped only stationary ones are counted
// otherwise the first net found is returned
int get_trapping_net(int x, int y, bool trapped)
{
int net, next;
for (net = igrd[x][y]; net != NON_ITEM; net = next)
{
next = mitm[net].link;
if (mitm[net].base_type == OBJ_MISSILES
&& mitm[net].sub_type == MI_THROWING_NET
&& (!trapped || item_is_stationary(mitm[net])))
{
return (net);
}
}
return (NON_ITEM);
}
// if there are more than one net on this square
// split off one of them for checking/setting values
static void maybe_split_nets(item_def &item, int x, int y)
{
if (item.quantity == 1)
{
set_item_stationary(item);
return;
}
item_def it;
it.base_type = item.base_type;
it.sub_type = item.sub_type;
it.plus = item.plus;
it.plus2 = item.plus2;
it.flags = item.flags;
it.special = item.special;
it.quantity = --item.quantity;
item_colour(it);
item.quantity = 1;
set_item_stationary(item);
copy_item_to_grid( it, x, y );
}
void mark_net_trapping(int x, int y)
{
int net = get_trapping_net(x,y);
if (net == NON_ITEM)
{
net = get_trapping_net(x,y, false);
if (net != NON_ITEM)
maybe_split_nets(mitm[net], x, y);
}
}
void monster_caught_in_net(monsters *mon, bolt &pbolt)
{
if (mon->body_size(PSIZE_BODY) >= SIZE_GIANT)
return;
if (mons_is_insubstantial(mon->type))
{
if (mons_near(mon) && player_monster_visible(mon))
mprf("The net passes right through %s!", mon->name(DESC_NOCAP_THE).c_str());
return;
}
const monsters* mons = static_cast<const monsters*>(mon);
bool mon_flies = mons->flies();
if (mon_flies && !mons_is_confused(mons))
{
simple_monster_message(mon, " darts out from under the net!");
return;
}
if (mons->type == MONS_OOZE || mons->type == MONS_PULSATING_LUMP)
{
simple_monster_message(mon, " oozes right through the net!");
return;
}
if (!mons_is_caught(mon) && mon->add_ench(ENCH_HELD))
{
if (mons_near(mon) && !player_monster_visible(mon))
mpr("Something gets caught in the net!");
else
simple_monster_message(mon, " is caught in the net!");
if (mon_flies)
{
simple_monster_message(mon, " falls like a stone!");
mons_check_pool(mon, pbolt.killer(), pbolt.beam_source);
}
}
}
void player_caught_in_net()
{
if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
return;
if (you.flies() && !you.confused())
{
mpr("You dart out from under the net!");
return;
}
if (!you.attribute[ATTR_HELD])
{
you.attribute[ATTR_HELD] = 10;
mpr("You become entangled in the net!");
// I guess levitation works differently, keeping both you
// and the net hovering above the floor
if (you.flies())
{
mpr("You fall like a stone!");
fall_into_a_pool(you.x_pos, you.y_pos, false, grd[you.x_pos][you.y_pos]);
}
}
}
static void dart_trap(bool trap_known, int trapped, bolt &pbolt, bool poison)
{
int damage_taken = 0;
int trap_hit, your_dodge;
if (one_chance_in(5) || (trap_known && !one_chance_in(4)))
{
mprf( "You avoid triggering a%s trap.", pbolt.name.c_str() );
return;
}
if (you.equip[EQ_SHIELD] != -1 && one_chance_in(3))
exercise( SK_SHIELDS, 1 );
std::string msg = "A" + pbolt.name + " shoots out and ";
if (random2( 20 + 5 * you.shield_blocks * you.shield_blocks )
< player_shield_class())
{
you.shield_blocks++;
msg += "hits your shield.";
mpr(msg.c_str());
}
else
{
// note that this uses full ( not random2limit(foo,40) )
// player_evasion.
trap_hit = (20 + (you.your_level * 2)) * random2(200) / 100;
your_dodge = player_evasion() + random2(you.dex) / 3
- 2 + (you.duration[DUR_REPEL_MISSILES] * 10);
if (trap_hit >= your_dodge && you.duration[DUR_DEFLECT_MISSILES] == 0)
{
msg += "hits you!";
mpr(msg.c_str());
if (poison && random2(100) < 50 - (3 * player_AC()) / 2
&& !player_res_poison())
{
poison_player( 1 + random2(3) );
}
damage_taken = roll_dice( pbolt.damage );
damage_taken -= random2( player_AC() + 1 );
if (damage_taken > 0)
ouch( damage_taken, 0, KILLED_BY_TRAP, pbolt.name.c_str() );
}
else
{
msg += "misses you.";
mpr(msg.c_str());
}
if (player_light_armour(true) && coinflip())
exercise( SK_DODGING, 1 );
}
pbolt.target_x = you.x_pos;
pbolt.target_y = you.y_pos;
if (coinflip())
itrap( pbolt, trapped );
} // end dart_trap()
//
// itrap takes location from target_x, target_y of bolt strcture.
//
void itrap( struct bolt &pbolt, int trapped )
{
object_class_type base_type = OBJ_MISSILES;
int sub_type = MI_DART;
switch (env.trap[trapped].type)
{
case TRAP_DART:
base_type = OBJ_MISSILES;
sub_type = MI_DART;
break;
case TRAP_ARROW:
base_type = OBJ_MISSILES;
sub_type = MI_ARROW;
break;
case TRAP_BOLT:
base_type = OBJ_MISSILES;
sub_type = MI_BOLT;
break;
case TRAP_SPEAR:
base_type = OBJ_WEAPONS;
sub_type = WPN_SPEAR;
break;
case TRAP_AXE:
base_type = OBJ_WEAPONS;
sub_type = WPN_HAND_AXE;
break;
case TRAP_NEEDLE:
base_type = OBJ_MISSILES;
sub_type = MI_NEEDLE;
break;
case TRAP_NET:
base_type = OBJ_MISSILES;
sub_type = MI_THROWING_NET;
break;
default:
return;
}
trap_item( base_type, sub_type, pbolt.target_x, pbolt.target_y );
return;
} // end itrap()
void handle_traps(char trt, int i, bool trap_known)
{
struct bolt beam;
switch (trt)
{
case TRAP_DART:
beam.name = " dart";
beam.damage = dice_def( 1, 4 + (you.your_level / 2) );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_NEEDLE:
beam.name = " needle";
beam.damage = dice_def( 1, 0 );
dart_trap(trap_known, i, beam, true);
break;
case TRAP_ARROW:
beam.name = "n arrow";
beam.damage = dice_def( 1, 7 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_BOLT:
beam.name = " bolt";
beam.damage = dice_def( 1, 13 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_SPEAR:
beam.name = " spear";
beam.damage = dice_def( 1, 10 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_AXE:
beam.name = "n axe";
beam.damage = dice_def( 1, 15 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_TELEPORT:
mpr("You enter a teleport trap!");
if (scan_randarts(RAP_PREVENT_TELEPORTATION))
mpr("You feel a weird sense of stasis.");
else
you_teleport_now( true );
break;
case TRAP_AMNESIA:
mpr("You feel momentarily disoriented.");
if (!wearing_amulet(AMU_CLARITY))
forget_map(random2avg(100, 2));
break;
case TRAP_BLADE:
if (trap_known && one_chance_in(3))
mpr("You avoid triggering a blade trap.");
else if (random2limit(player_evasion(), 40)
+ (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 8)
{
mpr("A huge blade swings just past you!");
}
else
{
mpr("A huge blade swings out and slices into you!");
ouch( (you.your_level * 2) + random2avg(29, 2)
- random2(1 + player_AC()), 0, KILLED_BY_TRAP, " blade" );
}
break;
case TRAP_NET:
if (trap_known && one_chance_in(3))
mpr("A net swings high above you.");
else
{
if (random2limit(player_evasion(), 40)
+ (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 12)
{
mpr("A net drops to the ground!");
}
else
{
mpr("A large net falls onto you!");
player_caught_in_net();
}
trap_item( OBJ_MISSILES, MI_THROWING_NET, env.trap[i].x, env.trap[i].y );
if (you.attribute[ATTR_HELD])
mark_net_trapping(you.x_pos, you.y_pos);
grd[env.trap[i].x][env.trap[i].y] = DNGN_FLOOR;
env.trap[i].type = TRAP_UNASSIGNED;
}
break;
case TRAP_ZOT:
default:
mpr((trap_known) ? "You enter the Zot trap."
: "Oh no! You have blundered into a Zot trap!");
miscast_effect( SPTYP_RANDOM, random2(30) + you.your_level,
75 + random2(100), 3, "a Zot trap" );
break;
}
learned_something_new(TUT_SEEN_TRAP, you.x_pos, you.y_pos);
} // end handle_traps()
void disarm_trap( struct dist &disa )
{
if (you.duration[DUR_BERSERKER])
{
canned_msg(MSG_TOO_BERSERK);
return;
}
int i, j;
for (i = 0; i < MAX_TRAPS; i++)
{
if (env.trap[i].x == you.x_pos + disa.dx
&& env.trap[i].y == you.y_pos + disa.dy)
{
break;
}
if (i == MAX_TRAPS - 1)
{
mpr("Error - couldn't find that trap.");
return;
}
}
if (trap_category(env.trap[i].type) == DNGN_TRAP_MAGICAL)
{
mpr("You can't disarm that trap.");
return;
}
if (random2(you.skills[SK_TRAPS_DOORS] + 2) <= random2(you.your_level + 5))
{
mpr("You failed to disarm the trap.");
you.turn_is_over = true;
if (random2(you.dex) > 5 + random2(5 + you.your_level))
exercise(SK_TRAPS_DOORS, 1 + random2(you.your_level / 5));
else
{
if (env.trap[i].type == TRAP_NET &&
(env.trap[i].x != you.x_pos || env.trap[i].y != you.y_pos))
{
if (coinflip())
return;
mpr("You stumble into the trap!");
move_player_to_grid( env.trap[i].x, env.trap[i].y, true, false, true);
}
else
handle_traps(env.trap[i].type, i, false);
if (coinflip())
exercise(SK_TRAPS_DOORS, 1);
}
return;
}
mpr("You have disarmed the trap.");
struct bolt beam;
beam.target_x = you.x_pos + disa.dx;
beam.target_y = you.y_pos + disa.dy;
if (env.trap[i].type == TRAP_NET)
trap_item( OBJ_MISSILES, MI_THROWING_NET, beam.target_x, beam.target_y );
else if (env.trap[i].type != TRAP_BLADE
&& trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL)
{
const int num_to_make = 10 + random2(you.skills[SK_TRAPS_DOORS]);
for (j = 0; j < num_to_make; j++)
{
// places items (eg darts), which will automatically stack
itrap(beam, i);
}
}
grd[you.x_pos + disa.dx][you.y_pos + disa.dy] = DNGN_FLOOR;
env.trap[i].type = TRAP_UNASSIGNED;
you.turn_is_over = true;
// reduced from 5 + random2(5)
exercise(SK_TRAPS_DOORS, 1 + random2(5) + (you.your_level / 5));
} // end disarm_trap()
// attempts to take a net off a given monster
// Do not expect gratitude for this!
// ----------------------------------
void remove_net_from(monsters *mon)
{
you.turn_is_over = true;
int net = get_trapping_net(mon->x, mon->y);
if (net == NON_ITEM)
{
mon->del_ench(ENCH_HELD, true);
return;
}
// factor in whether monster is paralysed or invisible
int paralys = 0;
if (mons_is_paralysed(mon)) // makes this easier
paralys = random2(5);
int invis = 0;
if (!player_monster_visible(mon)) // makes this harder
invis = 3 + random2(5);
bool net_destroyed = false;
if ( random2(you.skills[SK_TRAPS_DOORS] + 2) + paralys
<= random2( 2*mon->body_size(PSIZE_BODY) + 3 ) + invis)
{
if (one_chance_in(you.skills[SK_TRAPS_DOORS] + you.dex/2))
{
mitm[net].plus--;
mpr("You tear at the net.");
if (mitm[net].plus < -7)
{
mpr("Whoops! The net comes apart in your hands!");
mon->del_ench(ENCH_HELD, true);
destroy_item(net);
net_destroyed = true;
}
}
if (!net_destroyed)
{
if (player_monster_visible(mon))
{
mprf("You fail to remove the net from %s.",
mon->name(DESC_NOCAP_THE).c_str());
}
else
mpr("You fail to remove the net.");
}
if (random2(you.dex) > 5 + random2( 2*mon->body_size(PSIZE_BODY) ))
exercise(SK_TRAPS_DOORS, 1 + random2(mon->body_size(PSIZE_BODY)/2));
return;
}
mon->del_ench(ENCH_HELD, true);
remove_item_stationary(mitm[net]);
if (player_monster_visible(mon))
mprf("You free %s.", mon->name(DESC_NOCAP_THE).c_str());
else
mpr("You loosen the net.");
}
void free_self_from_net(bool damage_net)
{
int net = get_trapping_net(you.x_pos, you.y_pos);
if (net == NON_ITEM) // really shouldn't happen!
{
you.attribute[ATTR_HELD] = 0;
return;
}
int hold = mitm[net].plus;
if (damage_net)
{
mpr("You struggle against the net.");
int damage = 1;
// extra damage for cutting weapons
if (you.equip[EQ_WEAPON] != -1
&& can_cut_meat(you.inv[you.equip[EQ_WEAPON]]))
{
damage++;
}
if (you.body_size(PSIZE_BODY) > SIZE_MEDIUM)
damage++;
if (hold < 0 && !one_chance_in(-hold/2))
damage++;
if (you.duration[DUR_BERSERKER])
damage *= 2;
mitm[net].plus -= damage;
if (mitm[net].plus < -7)
{
mpr("You rip the net and break free!");
dec_mitm_item_quantity( net, 1 );
you.attribute[ATTR_HELD] = 0;
return;
}
}
else // you try to escape
{
mpr("You struggle to escape from the net.");
you.attribute[ATTR_HELD]--;
if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM)
you.attribute[ATTR_HELD]--;
if (hold < 0 && !one_chance_in(-hold/2))
you.attribute[ATTR_HELD]--;
if (you.attribute[ATTR_HELD] <= 0)
{
mpr("You break free from the net!");
you.attribute[ATTR_HELD] = 0;
remove_item_stationary(mitm[net]);
return;
}
}
}
bool trap_item(object_class_type base_type, char sub_type,
char beam_x, char beam_y)
{
item_def item;
item.base_type = base_type;
item.sub_type = sub_type;
item.plus = 0;
item.plus2 = 0;
item.flags = 0;
item.special = 0;
item.quantity = 1;
if (base_type == OBJ_MISSILES)
{
if (sub_type == MI_NEEDLE)
set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
else
set_item_ego_type( item, OBJ_MISSILES, SPMSL_NORMAL );
}
else
{
set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
}
item_colour(item);
if (igrd[beam_x][beam_y] != NON_ITEM)
{
if (items_stack( item, mitm[ igrd[beam_x][beam_y] ] ))
{
inc_mitm_item_quantity( igrd[beam_x][beam_y], 1 );
return (false);
}
// don't want to go overboard here. Will only generate up to three
// separate trap items, or less if there are other items present.
if (mitm[ igrd[beam_x][beam_y] ].link != NON_ITEM
&& (item.base_type != OBJ_MISSILES || item.sub_type != MI_THROWING_NET))
{
if (mitm[ mitm[ igrd[beam_x][beam_y] ].link ].link != NON_ITEM)
return (false);
}
} // end of if igrd != NON_ITEM
return (!copy_item_to_grid( item, beam_x, beam_y, 1 ));
} // end trap_item()
// returns appropriate trap symbol for a given trap type {dlb}
dungeon_feature_type trap_category(trap_type type)
{
switch (type)
{
case TRAP_TELEPORT:
case TRAP_AMNESIA:
case TRAP_ZOT:
return (DNGN_TRAP_MAGICAL);
case TRAP_DART:
case TRAP_ARROW:
case TRAP_SPEAR:
case TRAP_AXE:
case TRAP_BLADE:
case TRAP_BOLT:
case TRAP_NEEDLE:
case TRAP_NET:
default: // what *would* be the default? {dlb}
return (DNGN_TRAP_MECHANICAL);
}
} // end trap_category()
// returns index of the trap for a given (x,y) coordinate pair {dlb}
int trap_at_xy(int which_x, int which_y)
{
for (int which_trap = 0; which_trap < MAX_TRAPS; which_trap++)
{
if (env.trap[which_trap].x == which_x &&
env.trap[which_trap].y == which_y &&
env.trap[which_trap].type != TRAP_UNASSIGNED)
{
return (which_trap);
}
}
// no idea how well this will be handled elsewhere: {dlb}
return (-1);
} // end trap_at_xy()
trap_type trap_type_at_xy(int x, int y)
{
const int idx = trap_at_xy(x, y);
return (idx == -1? NUM_TRAPS : env.trap[idx].type);
}
/*
* File: terrain.h
* Summary: Terrain related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.h
*/
#ifndef TERRAIN_H
#define TERRAIN_H
#include "enum.h"
class coord_def;
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
unsigned char terrain );
bool grid_is_wall(dungeon_feature_type grid);
bool grid_is_opaque(dungeon_feature_type grid);
bool grid_is_solid(dungeon_feature_type grid);
bool grid_is_stone_stair(dungeon_feature_type grid);
bool grid_is_rock_stair(dungeon_feature_type grid);
bool grid_is_solid(int x, int y);
bool grid_is_solid(const coord_def &c);
bool grid_is_trap(dungeon_feature_type grid);
command_type grid_stair_direction(dungeon_feature_type grid);
bool grid_sealable_portal(dungeon_feature_type grid);
bool grid_is_portal(dungeon_feature_type grid);
bool grid_is_water(dungeon_feature_type grid);
bool grid_is_watery(dungeon_feature_type grid);
god_type grid_altar_god( dungeon_feature_type grid );
dungeon_feature_type altar_for_god( god_type god );
bool grid_is_branch_stairs( dungeon_feature_type grid );
int grid_secret_door_appearance( int gx, int gy );
bool grid_destroys_items( dungeon_feature_type grid );
const char *grid_item_destruction_message( dungeon_feature_type grid );
// Terrain changed under 'pos', perform necessary effects.
void dungeon_terrain_changed(const coord_def &pos,
dungeon_feature_type feat = DNGN_UNSEEN,
bool affect_player = true,
bool preserve_features = false,
bool preserve_items = false);
#endif
/*
* File: terrain.cc
* Summary: Terrain related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.cc
*/
#include "externs.h"
#include "terrain.h"
#include "dgnevent.h"
#include "itemprop.h"
#include "items.h"
#include "message.h"
#include "misc.h"
#include "monplace.h"
#include "monstuff.h"
#include "mstuff2.h"
#include "ouch.h"
#include "overmap.h"
#include "player.h"
#include "religion.h"
#include "spells3.h"
#include "stuff.h"
#include "view.h"
bool grid_is_wall( dungeon_feature_type grid )
{
return (grid == DNGN_ROCK_WALL
|| grid == DNGN_STONE_WALL
|| grid == DNGN_METAL_WALL
|| grid == DNGN_GREEN_CRYSTAL_WALL
|| grid == DNGN_WAX_WALL
|| grid == DNGN_PERMAROCK_WALL);
}
bool grid_is_stone_stair(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_STONE_STAIRS_UP_I:
case DNGN_STONE_STAIRS_UP_II:
case DNGN_STONE_STAIRS_UP_III:
case DNGN_STONE_STAIRS_DOWN_I:
case DNGN_STONE_STAIRS_DOWN_II:
case DNGN_STONE_STAIRS_DOWN_III:
return (true);
default:
return (false);
}
}
bool grid_is_rock_stair(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_ROCK_STAIRS_UP:
case DNGN_ROCK_STAIRS_DOWN:
return (true);
default:
return (false);
}
}
bool grid_sealable_portal(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_ENTER_HELL:
case DNGN_ENTER_ABYSS:
case DNGN_ENTER_PANDEMONIUM:
case DNGN_ENTER_LABYRINTH:
case DNGN_ENTER_PORTAL_VAULT:
return (true);
default:
return (false);
}
}
bool grid_is_portal(dungeon_feature_type grid)
{
return (grid == DNGN_ENTER_PORTAL_VAULT || grid == DNGN_EXIT_PORTAL_VAULT);
}
command_type grid_stair_direction(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_STONE_STAIRS_UP_I:
case DNGN_STONE_STAIRS_UP_II:
case DNGN_STONE_STAIRS_UP_III:
case DNGN_ROCK_STAIRS_UP:
case DNGN_RETURN_FROM_ORCISH_MINES:
case DNGN_RETURN_FROM_HIVE:
case DNGN_RETURN_FROM_LAIR:
case DNGN_RETURN_FROM_SLIME_PITS:
case DNGN_RETURN_FROM_VAULTS:
case DNGN_RETURN_FROM_CRYPT:
case DNGN_RETURN_FROM_HALL_OF_BLADES:
case DNGN_RETURN_FROM_ZOT:
case DNGN_RETURN_FROM_TEMPLE:
case DNGN_RETURN_FROM_SNAKE_PIT:
case DNGN_RETURN_FROM_ELVEN_HALLS:
case DNGN_RETURN_FROM_TOMB:
case DNGN_RETURN_FROM_SWAMP:
case DNGN_RETURN_FROM_SHOALS:
case DNGN_RETURN_RESERVED_2:
case DNGN_RETURN_RESERVED_3:
case DNGN_RETURN_RESERVED_4:
case DNGN_ENTER_SHOP:
case DNGN_EXIT_HELL:
case DNGN_EXIT_PORTAL_VAULT:
return (CMD_GO_UPSTAIRS);
case DNGN_ENTER_PORTAL_VAULT:
case DNGN_ENTER_HELL:
case DNGN_ENTER_LABYRINTH:
case DNGN_STONE_STAIRS_DOWN_I:
case DNGN_STONE_STAIRS_DOWN_II:
case DNGN_STONE_STAIRS_DOWN_III:
case DNGN_ROCK_STAIRS_DOWN:
case DNGN_ENTER_DIS:
case DNGN_ENTER_GEHENNA:
case DNGN_ENTER_COCYTUS:
case DNGN_ENTER_TARTARUS:
case DNGN_ENTER_ABYSS:
case DNGN_EXIT_ABYSS:
case DNGN_ENTER_PANDEMONIUM:
case DNGN_EXIT_PANDEMONIUM:
case DNGN_TRANSIT_PANDEMONIUM:
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:
case DNGN_ENTER_RESERVED_2:
case DNGN_ENTER_RESERVED_3:
case DNGN_ENTER_RESERVED_4:
return (CMD_GO_DOWNSTAIRS);
default:
return (CMD_NO_CMD);
}
}
bool grid_is_opaque( dungeon_feature_type grid )
{
return (grid < DNGN_MINSEE && grid != DNGN_ORCISH_IDOL);
}
bool grid_is_solid( dungeon_feature_type grid )
{
return (grid < DNGN_MINMOVE);
}
bool grid_is_solid( int x, int y )
{
return (grid_is_solid(grd[x][y]));
}
bool grid_is_solid(const coord_def &c)
{
return (grid_is_solid(grd(c)));
}
bool grid_is_trap(dungeon_feature_type grid)
{
return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
|| grid == DNGN_TRAP_III);
}
bool grid_is_water( dungeon_feature_type grid )
{
return (grid == DNGN_SHALLOW_WATER || grid == DNGN_DEEP_WATER);
}
bool grid_is_watery( dungeon_feature_type grid )
{
return (grid_is_water(grid) || grid == DNGN_BLUE_FOUNTAIN);
}
bool grid_destroys_items( dungeon_feature_type grid )
{
return (grid == DNGN_LAVA || grid == DNGN_DEEP_WATER);
}
// returns 0 if grid is not an altar, else it returns the GOD_* type
god_type grid_altar_god( dungeon_feature_type grid )
{
if (grid >= DNGN_ALTAR_ZIN && grid <= DNGN_ALTAR_BEOGH)
return (static_cast<god_type>( grid - DNGN_ALTAR_ZIN + 1 ));
return (GOD_NO_GOD);
}
// returns DNGN_FLOOR for non-gods, otherwise returns the altar for
// the god.
dungeon_feature_type altar_for_god( god_type god )
{
if (god == GOD_NO_GOD || god >= NUM_GODS)
return (DNGN_FLOOR); // Yeah, lame. Tell me about it.
return static_cast<dungeon_feature_type>(DNGN_ALTAR_ZIN + god - 1);
}
bool grid_is_branch_stairs( dungeon_feature_type grid )
{
return ((grid >= DNGN_ENTER_ORCISH_MINES && grid <= DNGN_ENTER_RESERVED_4)
|| (grid >= DNGN_ENTER_DIS && grid <= DNGN_ENTER_TARTARUS));
}
int grid_secret_door_appearance( int gx, int gy )
{
int ret = DNGN_FLOOR;
for (int dx = -1; dx <= 1; dx++)
{
for (int dy = -1; dy <= 1; dy++)
{
// only considering orthogonal grids
if ((abs(dx) + abs(dy)) % 2 == 0)
continue;
const dungeon_feature_type targ = grd[gx + dx][gy + dy];
if (!grid_is_wall( targ ))
continue;
if (ret == DNGN_FLOOR)
ret = targ;
else if (ret != targ)
ret = ((ret < targ) ? ret : targ);
}
}
return ((ret == DNGN_FLOOR) ? DNGN_ROCK_WALL
: ret);
}
const char *grid_item_destruction_message( dungeon_feature_type grid )
{
return grid == DNGN_DEEP_WATER? "You hear a splash."
: grid == DNGN_LAVA ? "You hear a sizzling splash."
: "You hear a crunching noise.";
}
static coord_def dgn_find_nearest_square(
const coord_def &pos,
bool (*acceptable)(const coord_def &),
bool (*traversable)(const coord_def &) = NULL)
{
memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
std::list<coord_def> points[2];
int iter = 0;
points[iter].push_back(pos);
while (!points[iter].empty())
{
for (std::list<coord_def>::iterator i = points[iter].begin();
i != points[iter].end(); ++i)
{
const coord_def &p = *i;
if (p != pos && acceptable(p))
return (p);
travel_point_distance[p.x][p.y] = 1;
for (int yi = -1; yi <= 1; ++yi)
{
for (int xi = -1; xi <= 1; ++xi)
{
if (!xi && !yi)
continue;
const coord_def np = p + coord_def(xi, yi);
if (!in_bounds(np) || travel_point_distance[np.x][np.y])
continue;
if (traversable && !traversable(np))
continue;
points[!iter].push_back(np);
}
}
}
points[iter].clear();
iter = !iter;
}
coord_def unfound;
return (unfound);
}
static bool item_safe_square(const coord_def &pos)
{
const dungeon_feature_type feat = grd(pos);
return (is_traversable(feat) && !grid_destroys_items(feat));
}
// Moves an item on the floor to the nearest adjacent floor-space.
static bool dgn_shift_item(const coord_def &pos, item_def &item)
{
const coord_def np = dgn_find_nearest_square(pos, item_safe_square);
if (in_bounds(np) && np != pos)
{
int index = item.index();
move_item_to_grid(&index, np.x, np.y);
return (true);
}
return (false);
}
static bool is_critical_feature(dungeon_feature_type feat)
{
return (grid_stair_direction(feat) != CMD_NO_CMD
|| grid_altar_god(feat) != GOD_NO_GOD);
}
static bool is_feature_shift_target(const coord_def &pos)
{
return (grd(pos) == DNGN_FLOOR && !dungeon_events.has_listeners_at(pos));
}
static bool dgn_shift_feature(const coord_def &pos)
{
const dungeon_feature_type dfeat = grd(pos);
if (!is_critical_feature(dfeat) && !env.markers.find(pos, MAT_ANY))
return (false);
const coord_def dest =
dgn_find_nearest_square(pos, is_feature_shift_target);
if (in_bounds(dest) && dest != pos)
{
grd(dest) = dfeat;
if (dfeat == DNGN_ENTER_SHOP)
{
if (shop_struct *s = get_shop(pos.x, pos.y))
{
s->x = dest.x;
s->y = dest.y;
}
}
env.markers.move(pos, dest);
dungeon_events.move_listeners(pos, dest);
}
return (true);
}
static void dgn_check_terrain_items(const coord_def &pos, bool preserve_items)
{
const dungeon_feature_type grid = grd(pos);
if (grid_is_solid(grid) || grid_destroys_items(grid))
{
int item = igrd(pos);
bool did_destroy = false;
while (item != NON_ITEM)
{
const int curr = item;
item = mitm[item].link;
// Game-critical item.
if (preserve_items || item_is_critical(mitm[curr]))
dgn_shift_item(pos, mitm[curr]);
else
{
destroy_item(curr);
did_destroy = true;
}
}
if (did_destroy && player_can_hear(pos))
mprf(MSGCH_SOUND, grid_item_destruction_message(grid));
}
}
static void dgn_check_terrain_monsters(const coord_def &pos)
{
const int mindex = mgrd(pos);
if (mindex != NON_MONSTER)
{
monsters *mons = &menv[mindex];
if (grid_is_solid(grd(pos)))
monster_teleport(mons, true, false);
else
mons_check_pool(mons, KILL_MISC, -1);
}
}
void dungeon_terrain_changed(const coord_def &pos,
dungeon_feature_type nfeat,
bool affect_player,
bool preserve_features,
bool preserve_items)
{
if (nfeat != DNGN_UNSEEN)
{
if (preserve_features)
dgn_shift_feature(pos);
unnotice_feature(level_pos(level_id::current(), pos));
grd(pos) = nfeat;
env.grid_colours(pos) = BLACK;
if (is_notable_terrain(nfeat) && see_grid(pos))
seen_notable_thing(nfeat, pos.x, pos.y);
}
dgn_check_terrain_items(pos, preserve_items);
if (affect_player && pos == you.pos())
{
if (!grid_is_solid(grd(pos)))
{
if (!you.flies())
move_player_to_grid(pos.x, pos.y, false, true, false);
}
else
you_teleport_now(true, false);
}
dgn_check_terrain_monsters(pos);
}
// returns true if we manage to scramble free.
bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
unsigned char terrain )
{
bool escape = false;
FixedVector< char, 2 > empty;
if (you.species == SP_MERFOLK && terrain == DNGN_DEEP_WATER)
{
// These can happen when we enter deep water directly -- bwr
merfolk_start_swimming();
return (false);
}
// sanity check
if (terrain != DNGN_LAVA && beogh_water_walk())
return (false);
mprf("You fall into the %s!",
(terrain == DNGN_LAVA) ? "lava" :
(terrain == DNGN_DEEP_WATER) ? "water"
: "programming rift");
more();
mesclr();
if (terrain == DNGN_LAVA)
{
const int resist = player_res_fire();
if (resist <= 0)
{
mpr( "The lava burns you to a cinder!" );
ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
}
else
{
// should boost # of bangs per damage in the future {dlb}
mpr( "The lava burns you!" );
ouch( (10 + roll_dice(2,50)) / resist, 0, KILLED_BY_LAVA );
}
expose_player_to_element( BEAM_LAVA, 14 );
}
// a distinction between stepping and falling from you.duration[DUR_LEVITATION]
// prevents stepping into a thin stream of lava to get to the other side.
if (scramble())
{
if (allow_shift)
{
if (empty_surrounds( you.x_pos, you.y_pos, DNGN_FLOOR, 1,
false, empty ))
{
escape = true;
}
else
{
escape = false;
}
}
else
{
// back out the way we came in, if possible
if (grid_distance( you.x_pos, you.y_pos, entry_x, entry_y ) == 1
&& (entry_x != empty[0] || entry_y != empty[1])
&& mgrd[entry_x][entry_y] == NON_MONSTER)
{
escape = true;
empty[0] = entry_x;
empty[1] = entry_y;
}
else // zero or two or more squares away, with no way back
{
escape = false;
}
}
}
else
{
mpr("You try to escape, but your burden drags you down!");
}
if (escape)
{
const coord_def pos(empty[0], empty[1]);
if (in_bounds(pos) && !is_grid_dangerous(grd(pos)))
{
mpr("You manage to scramble free!");
move_player_to_grid( empty[0], empty[1], false, false, true );
if (terrain == DNGN_LAVA)
expose_player_to_element( BEAM_LAVA, 14 );
return (true);
}
}
mpr("You drown...");
if (terrain == DNGN_LAVA)
ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
else if (terrain == DNGN_DEEP_WATER)
ouch( INSTANT_DEATH, 0, KILLED_BY_WATER );
return (false);
} // end fall_into_a_pool()
enum tag_type // used during save/load process to identify data blocks
{
TAG_VERSION = 0, // should NEVER be read in!
TAG_YOU = 1, // 'you' structure
TAG_YOU_ITEMS, // your items
TAG_YOU_DUNGEON, // dungeon specs (stairs, branches, features)
TAG_LEVEL, // various grids & clouds
TAG_LEVEL_ITEMS, // items/traps
TAG_LEVEL_MONSTERS, // monsters
TAG_GHOST, // ghost
TAG_LEVEL_ATTITUDE, // monster attitudes
TAG_LOST_MONSTERS, // monsters in transit
NUM_TAGS
};
enum tag_file_type // file types supported by tag system
{
TAGTYPE_PLAYER=0, // Foo.sav
TAGTYPE_LEVEL, // Foo.00a, .01a, etc.
TAGTYPE_GHOST, // bones.xxx
/*
* File: state.h
* Summary: Game state.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-10 11:21:32 -0700 (Mon, 10 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 7/11/07 MPC Split off from externs.h
*/
#ifndef STATE_H
#define STATE_H
// Track various aspects of Crawl game state.
struct game_state
{
bool mouse_enabled; // True if mouse input is currently relevant.
bool waiting_for_command; // True when the game is waiting for a command.
bool terminal_resized; // True if the term was resized and we need to
// take action to handle it.
bool io_inited; // Is curses or the equivalent initialised?
bool need_save; // Set to true when game has started.
bool saving_game; // Set to true while in save_game.
bool updating_scores; // Set to true while updating hiscores.
int seen_hups; // Set to true if SIGHUP received.
bool map_stat_gen; // Set if we're generating stats on maps.
bool unicode_ok; // Is unicode support available?
std::string (*glyph2strfn)(unsigned glyph);
int (*multibyte_strlen)(const std::string &s);
void (*terminal_resize_handler)();
void (*terminal_resize_check)();
game_state() : mouse_enabled(false), waiting_for_command(false),
terminal_resized(false), io_inited(false), need_save(false),
saving_game(false), updating_scores(false),
seen_hups(0), map_stat_gen(false), unicode_ok(false),
glyph2strfn(NULL), multibyte_strlen(NULL),
terminal_resize_handler(NULL), terminal_resize_check(NULL)
{
}
void check_term_size() const
{
if (terminal_resize_check)
(*terminal_resize_check)();
}
};
extern game_state crawl_state;
#endif
enum spschool_flag_type
{
SPTYP_NONE = 0, // "0" is reserved for no type at all {dlb}
SPTYP_CONJURATION = 1, // was 11, but only for old typematch routine {dlb}
SPTYP_ENCHANTMENT = 1<<1,
SPTYP_FIRE = 1<<2,
SPTYP_ICE = 1<<3,
SPTYP_TRANSMIGRATION = 1<<4,
SPTYP_NECROMANCY = 1<<5,
SPTYP_SUMMONING = 1<<6,
SPTYP_DIVINATION = 1<<7,
SPTYP_TRANSLOCATION = 1<<8,
SPTYP_POISON = 1<<9,
SPTYP_EARTH = 1<<10,
SPTYP_AIR = 1<<11,
SPTYP_HOLY = 1<<12, //jmf: moved to accomodate "random" miscast f/x
SPTYP_LAST_EXPONENT = 12, //jmf: ``NUM_SPELL_TYPES'' kinda useless
NUM_SPELL_TYPES = 14,
SPTYP_RANDOM = 1<<14
};
enum spflag_type
{
SPFLAG_NONE = 0x0000,
SPFLAG_DIR_OR_TARGET = 0x0001, // use DIR_NONE targeting
SPFLAG_TARGET = 0x0002, // use DIR_TARGET targeting
SPFLAG_GRID = 0x0004, // use DIR_GRID targeting
SPFLAG_DIR = 0x0008, // use DIR_DIR targeting
SPFLAG_TARGETING_MASK = 0x000f, // used to test for targeting
SPFLAG_HELPFUL = 0x0010, // TARG_FRIENDS used
SPFLAG_NOT_SELF = 0x0020, // aborts on isMe
SPFLAG_UNHOLY = 0x0040 // counts at "unholy"
};
enum spret_type
{
SPRET_ABORT = 0, // should be left as 0
SPRET_FAIL,
SPRET_SUCCESS
};
/*
* File: ray.h
* Summary: Ray definition
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-10 11:21:32 -0700 (Mon, 10 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 7/11/07 MPC Split off from externs.h
*/
#ifndef RAY_H
#define RAY_H
struct ray_def
{
public:
double accx;
double accy;
double slope;
// Quadrant 1: down-right
// Quadrant 2: down-left
// Quadrant 3: up-left
// Quadrant 4: up-right
int quadrant;
int fullray_idx; // for cycling: where did we come from?
public:
ray_def();
int x() const { return static_cast<int>(accx); }
int y() const { return static_cast<int>(accy); }
coord_def pos() const { return coord_def(x(), y()); }
// returns the direction taken (0,1,2)
int advance(bool shorten = false, const coord_def *p = NULL);
int advance_through(const coord_def &point);
void advance_and_bounce();
void regress();
private:
int raw_advance();
double reflect(bool x, double oldc, double newc) const;
double reflect(double x, double c) const;
void set_reflect_point(const double oldx, const double oldy,
double *newx, double *newy,
bool blocked_x, bool blocked_y);
};
#endif
enum randart_prop_type
{
RAP_BRAND, // 0
RAP_AC,
RAP_EVASION,
RAP_STRENGTH,
RAP_INTELLIGENCE,
RAP_DEXTERITY, // 5
RAP_FIRE,
RAP_COLD,
RAP_ELECTRICITY,
RAP_POISON,
RAP_NEGATIVE_ENERGY, // 10
RAP_MAGIC,
RAP_EYESIGHT,
RAP_INVISIBLE,
RAP_LEVITATE,
RAP_BLINK, // 15
RAP_CAN_TELEPORT,
RAP_BERSERK,
RAP_MAPPING,
RAP_NOISES,
RAP_PREVENT_SPELLCASTING, // 20
RAP_CAUSE_TELEPORTATION,
RAP_PREVENT_TELEPORTATION,
RAP_ANGRY,
RAP_METABOLISM,
RAP_MUTAGENIC, // 25
RAP_ACCURACY,
RAP_DAMAGE,
RAP_CURSED,
RAP_STEALTH,
RAP_NUM_PROPERTIES
};
/*
* File: place.h
* Summary: Place related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.h
*/
#ifndef PLACE_H
#define PLACE_H
#include "enum.h"
//////////////////////////////////////////////////////////////////////
// Places and names
//
unsigned short get_packed_place();
unsigned short get_packed_place( branch_type branch, int subdepth,
level_area_type level_type );
int place_branch(unsigned short place);
int place_depth(unsigned short place);
std::string short_place_name(unsigned short place);
std::string short_place_name(level_id id);
std::string place_name( unsigned short place, bool long_name = false,
bool include_number = true );
// Prepositional form of branch level name. For example, "in the
// Abyss" or "on level 3 of the Main Dungeon".
std::string prep_branch_level_name(unsigned short packed_place);
std::string prep_branch_level_name();
// Get displayable depth in the current branch, given the absolute
// depth.
int subdungeon_depth(branch_type branch, int depth);
// Get absolute depth given the displayable depth in the branch.
int absdungeon_depth(branch_type branch, int subdepth);
// Get displayable depth in the current branch.
int player_branch_depth();
bool single_level_branch(branch_type branch);
bool level_type_exits_up(level_area_type type);
bool level_type_exits_down(level_area_type type);
#endif
/*
* File: place.cc
* Summary: Place related functions.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-03 06:41:30 -0700 (Mon, 03 Sep 2007) $
*
* Change History (most recent first):
*
* <1> 9/11/07 MPC Split from misc.cc
*/
#include "externs.h"
#include "place.h"
#include "branch.h"
#include "travel.h"
// Do not attempt to use level_id if level_type != LEVEL_DUNGEON
std::string short_place_name(level_id id)
{
return id.describe();
}
int place_branch(unsigned short place)
{
const unsigned branch = (unsigned) ((place >> 8) & 0xFF);
const int lev = place & 0xFF;
return lev == 0xFF? -1 : (int) branch;
}
int place_depth(unsigned short place)
{
const int lev = place & 0xFF;
return lev == 0xFF? -1 : lev;
}
unsigned short get_packed_place( branch_type branch, int subdepth,
level_area_type level_type )
{
unsigned short place = (unsigned short)
( (static_cast<int>(branch) << 8) | (subdepth & 0xFF) );
if (level_type != LEVEL_DUNGEON)
place = (unsigned short) ( (static_cast<int>(level_type) << 8) | 0xFF );
return place;
}
unsigned short get_packed_place()
{
return get_packed_place( you.where_are_you,
subdungeon_depth(you.where_are_you, you.your_level),
you.level_type );
}
bool single_level_branch( branch_type branch )
{
return
branch >= 0 && branch < NUM_BRANCHES
&& branches[branch].depth == 1;
}
std::string place_name( unsigned short place, bool long_name,
bool include_number )
{
unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
int lev = place & 0xFF;
std::string result;
if (lev == 0xFF)
{
switch (branch)
{
case LEVEL_ABYSS:
return ( long_name ? "The Abyss" : "Abyss" );
case LEVEL_PANDEMONIUM:
return ( long_name ? "Pandemonium" : "Pan" );
case LEVEL_LABYRINTH:
return ( long_name ? "a Labyrinth" : "Lab" );
case LEVEL_PORTAL_VAULT:
return ( long_name ? "a Portal Chamber" : "Port" );
default:
return ( long_name ? "Buggy Badlands" : "Bug" );
}
}
result = (long_name ?
branches[branch].longname : branches[branch].abbrevname);
if ( include_number && branches[branch].depth != 1 )
{
char buf[200];
if ( long_name )
{
// decapitalize 'the'
if ( result.find("The") == 0 )
result[0] = 't';
snprintf( buf, sizeof buf, "Level %d of %s",
lev, result.c_str() );
}
else if (lev)
snprintf( buf, sizeof buf, "%s:%d", result.c_str(), lev );
else
snprintf( buf, sizeof buf, "%s:$", result.c_str() );
result = buf;
}
return result;
}
// Takes a packed 'place' and returns a compact stringified place name.
// XXX: This is done in several other places; a unified function to
// describe places would be nice.
std::string short_place_name(unsigned short place)
{
return place_name( place, false, true );
}
// Prepositional form of branch level name. For example, "in the
// Abyss" or "on level 3 of the Main Dungeon".
std::string prep_branch_level_name(unsigned short packed_place)
{
std::string place = place_name( packed_place, true, true );
if (place.length() && place != "Pandemonium")
place[0] = tolower(place[0]);
return (place.find("level") == 0?
"on " + place
: "in " + place);
}
// Use current branch and depth
std::string prep_branch_level_name()
{
return prep_branch_level_name( get_packed_place() );
}
int absdungeon_depth(branch_type branch, int subdepth)
{
if (branch >= BRANCH_VESTIBULE_OF_HELL && branch <= BRANCH_THE_PIT)
return subdepth + 27 - (branch == BRANCH_VESTIBULE_OF_HELL);
else
{
--subdepth;
while ( branch != BRANCH_MAIN_DUNGEON )
{
subdepth += branches[branch].startdepth;
branch = branches[branch].parent_branch;
}
}
return subdepth;
}
int subdungeon_depth(branch_type branch, int depth)
{
return depth - absdungeon_depth(branch, 0);
}
int player_branch_depth()
{
return subdungeon_depth(you.where_are_you, you.your_level);
}
// Returns true if exits from this type of level involve going upstairs.
bool level_type_exits_up(level_area_type type)
{
return (type == LEVEL_LABYRINTH || type == LEVEL_PORTAL_VAULT);
}
bool level_type_exits_down(level_area_type type)
{
return (type == LEVEL_PANDEMONIUM || type == LEVEL_ABYSS);
}
enum status_redraw_flag_type
{
REDRAW_HUNGER = 0x00000001,
REDRAW_BURDEN = 0x00000002,
REDRAW_LINE_1_MASK = 0x00000003,
REDRAW_PRAYER = 0x00000100,
REDRAW_REPEL_UNDEAD = 0x00000200,
REDRAW_BREATH = 0x00000400,
REDRAW_REPEL_MISSILES = 0x00000800,
REDRAW_REGENERATION = 0x00001000,
REDRAW_INSULATION = 0x00002000,
REDRAW_FLY = 0x00004000,
REDRAW_INVISIBILITY = 0x00008000,
REDRAW_LINE_2_MASK = 0x0000ff00,
enum kill_method_type
{
KILLED_BY_MONSTER, // 0
KILLED_BY_POISON,
KILLED_BY_CLOUD,
KILLED_BY_BEAM, // 3
KILLED_BY_DEATHS_DOOR, // should be deprecated, but you never know {dlb}
KILLED_BY_LAVA, // 5
KILLED_BY_WATER,
KILLED_BY_STUPIDITY,
KILLED_BY_WEAKNESS,
KILLED_BY_CLUMSINESS,
KILLED_BY_TRAP, // 10
KILLED_BY_LEAVING,
KILLED_BY_WINNING,
KILLED_BY_QUITTING,
KILLED_BY_DRAINING,
KILLED_BY_STARVATION, // 15
KILLED_BY_FREEZING,
KILLED_BY_BURNING,
KILLED_BY_WILD_MAGIC,
KILLED_BY_XOM,
KILLED_BY_STATUE, // 20
KILLED_BY_ROTTING,
KILLED_BY_TARGETTING,
KILLED_BY_SPORE,
KILLED_BY_TSO_SMITING,
KILLED_BY_PETRIFICATION, // 25
KILLED_BY_SOMETHING = 27,
KILLED_BY_FALLING_DOWN_STAIRS,
KILLED_BY_ACID,
KILLED_BY_CURARE,
KILLED_BY_MELTING,
KILLED_BY_BLEEDING,
KILLED_BY_BEOGH_SMITING,
/*
* File: mpr.h
* Summary: Functions used to print simple messages.
* Written by: Linley Henzell
*
* Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2007-09-02 05:40:44 -0700 (Sun, 02 Sep 2007) $
*
* Change History (most recent first):
*
* <2> 9/11/07 MPC Split off from message.h
* <2> 5/08/99 JDJ mpr takes a const char* instead of a char array.
* <1> -/--/-- LRH Created
*/
#ifndef MPR_H
#define MPR_H
// if you mess with this list, you'll need to make changes in initfile.cc
// to message_channel_names, and probably also to message.cc to colour
// everything properly
enum msg_channel_type
{
MSGCH_PLAIN, // regular text
MSGCH_PROMPT, // various prompts
MSGCH_GOD, // god/religion (param is god)
MSGCH_PRAY, // praying messages (param is god)
MSGCH_DURATION, // effect down/warnings
MSGCH_DANGER, // serious life threats (ie very large HP attacks)
MSGCH_WARN, // much less serious threats
MSGCH_FOOD, // hunger notices
MSGCH_RECOVERY, // recovery from disease/stat/poison condition
MSGCH_SOUND, // messages about things the player hears
MSGCH_TALK, // monster talk (param is monster type)
MSGCH_INTRINSIC_GAIN, // player level/stat/species-power gains
MSGCH_MUTATION, // player gain/lose mutations
MSGCH_MONSTER_SPELL, // monsters casting spells
MSGCH_MONSTER_ENCHANT,// monsters enchantments up and down
MSGCH_MONSTER_DAMAGE, // monster damage reports (param is level)
MSGCH_MONSTER_TARGET, // message marking the monster as a target
MSGCH_ROTTEN_MEAT, // messages about chunks/corpses becoming rotten
MSGCH_EQUIPMENT, // equipment listing messages
MSGCH_FLOOR_ITEMS, // like equipment, but lists of floor items
MSGCH_MULTITURN_ACTION, // delayed action messages
MSGCH_EXAMINE, // messages describing monsters, features, items
MSGCH_EXAMINE_FILTER, // "less important" instances of the above
MSGCH_DIAGNOSTICS, // various diagnostic messages
MSGCH_TUTORIAL, // messages for tutorial
NUM_MESSAGE_CHANNELS // always last
};
enum msg_colour_type
{
MSGCOL_BLACK = 0, // the order of these colours is important
MSGCOL_BLUE,
MSGCOL_GREEN,
MSGCOL_CYAN,
MSGCOL_RED,
MSGCOL_MAGENTA,
MSGCOL_BROWN,
MSGCOL_LIGHTGRAY,
MSGCOL_DARKGRAY,
MSGCOL_LIGHTBLUE,
MSGCOL_LIGHTGREEN,
MSGCOL_LIGHTCYAN,
MSGCOL_LIGHTMAGENTA,
MSGCOL_YELLOW,
MSGCOL_WHITE,
MSGCOL_DEFAULT, // use default colour
MSGCOL_ALTERNATE, // use secondary default colour scheme
MSGCOL_MUTED, // don't print messages
MSGCOL_PLAIN // same as plain channel
};
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: ability - acr - bang - beam - chardump - command - debug -
* decks - direct - effects - fight - files - food - it_use2 -
* it_use3 - item_use - items - macro - misc - monplace -
* monstuff - mstuff2 - mutation - ouch - overmap - player -
* religion - shopping - skills - spell - spl-book - spells -
* spells1 - spells2 - spells3 - spells4 - stuff - transfor -
* view
* *********************************************************************** */
void mpr(const char *inf, msg_channel_type channel = MSGCH_PLAIN, int param=0);
// 4.1-style mpr, currently named mprf for minimal disruption.
void mprf( msg_channel_type channel, int param, const char *format, ... );
void mprf( msg_channel_type channel, const char *format, ... );
void mprf( const char *format, ... );
#endif
enum mon_desc_type // things that cross categorical lines {dlb}
{
MDSC_LEAVES_HIDE, // 0
MDSC_REGENERATES,
MDSC_NOMSG_WOUNDS
};
#define YOU_KILL(x) ((x) == KILL_YOU || (x) == KILL_YOU_MISSILE \
|| (x) == KILL_YOU_CONF)
#define MON_KILL(x) ((x) == KILL_MON || (x) == KILL_MON_MISSILE)
enum band_type
{
BAND_NO_BAND = 0,
BAND_KOBOLDS = 1,
BAND_ORCS,
BAND_ORC_KNIGHT,
BAND_KILLER_BEES,
BAND_FLYING_SKULLS, // 5
BAND_SLIME_CREATURES,
BAND_YAKS,
BAND_UGLY_THINGS,
BAND_HELL_HOUNDS,
BAND_JACKALS, // 10
BAND_HELL_KNIGHTS,
BAND_ORC_HIGH_PRIEST,
BAND_GNOLLS, // 13
BAND_BUMBLEBEES = 16,
BAND_CENTAURS,
BAND_YAKTAURS,
BAND_INSUBSTANTIAL_WISPS,
BAND_OGRE_MAGE, // 20
BAND_DEATH_YAKS,
BAND_NECROMANCER,
BAND_BALRUG,
BAND_CACODEMON,
BAND_EXECUTIONER, // 25
BAND_HELLWING,
BAND_DEEP_ELF_FIGHTER,
BAND_DEEP_ELF_KNIGHT,
BAND_DEEP_ELF_HIGH_PRIEST,
BAND_KOBOLD_DEMONOLOGIST, // 30
BAND_NAGAS,
BAND_WAR_DOGS,
BAND_GREY_RATS,
BAND_GREEN_RATS,
BAND_ORANGE_RATS, // 35
BAND_SHEEP,
BAND_GHOULS,
BAND_DEEP_TROLLS,
BAND_HOGS,
BAND_HELL_HOGS, // 40
BAND_GIANT_MOSQUITOES,
BAND_BOGGARTS,
BAND_BLINK_FROGS,
BAND_SKELETAL_WARRIORS, // 44
BAND_DRACONIAN, // 45
BAND_PANDEMONIUM_DEMON,
NUM_BANDS // always last
};
enum demon_class_type
{
DEMON_LESSER, // 0: Class V
DEMON_COMMON, // 1: Class II-IV
DEMON_GREATER, // 2: Class I
DEMON_RANDOM // any of the above
};
enum dragon_class_type
{
DRAGON_LIZARD,
DRAGON_DRACONIAN,
DRAGON_DRAGON
};
enum proximity_type // proximity to player to create monster
{
PROX_ANYWHERE,
PROX_CLOSE_TO_PLAYER,
PROX_AWAY_FROM_PLAYER,
PROX_NEAR_STAIRS
};
enum corpse_effect_type
{
CE_NOCORPSE, // 0
CE_CLEAN, // 1
CE_CONTAMINATED, // 2
CE_POISONOUS, // 3
CE_HCL, // 4
CE_MUTAGEN_RANDOM, // 5
CE_MUTAGEN_GOOD, // 6 - may be worth implementing {dlb}
CE_MUTAGEN_BAD, // 7 - may be worth implementing {dlb}
CE_RANDOM, // 8 - not used, but may be worth implementing {dlb}
CE_ROTTEN = 50 // 50 - must remain at 50 for now {dlb}
};
enum gender_type
{
GENDER_NEUTER,
GENDER_MALE,
GENDER_FEMALE
};
enum mon_attack_type
{
AT_NONE,
AT_HIT, // including weapon attacks
AT_BITE,
AT_STING,
AT_SPORE,
AT_TOUCH,
AT_ENGULF,
AT_CLAW,
AT_TAIL_SLAP,
AT_BUTT,
AT_SHOOT // attack representing missile damage for M_ARCHER
};
enum mon_attack_flavour
{
AF_PLAIN,
AF_ACID,
AF_BLINK,
AF_COLD,
AF_CONFUSE,
AF_DISEASE,
AF_DRAIN_DEX,
AF_DRAIN_STR,
AF_DRAIN_XP,
AF_ELEC,
AF_FIRE,
AF_HUNGER,
AF_MUTATE,
AF_BAD_MUTATE,
AF_PARALYSE,
AF_POISON,
AF_POISON_NASTY,
AF_POISON_MEDIUM,
AF_POISON_STRONG,
AF_POISON_STR,
AF_ROT,
AF_VAMPIRIC,
AF_KLOWN,
AF_DISTORT,
AF_RAGE
};
// properties of the monster class (other than resists/vulnerabilities)
enum mons_class_flags
{
M_NO_FLAGS = 0,
M_SPELLCASTER = (1<< 0), // any non-physical-attack powers,
M_ACTUAL_SPELLS = (1<< 1), // monster is a wizard,
M_PRIEST = (1<< 2), // monster is a priest
M_FIGHTER = (1<< 3), // monster is skilled fighter
M_FLIES = (1<< 4), // will crash to ground if paralysed?
M_LEVITATE = (1<< 5), // ... but not if this is set
M_INVIS = (1<< 6), // is created invis
M_SEE_INVIS = (1<< 7), // can see invis
M_SENSE_INVIS = (1<< 8), // can sense invisible things
M_SPEAKS = (1<< 9), // uses talking code
M_CONFUSED = (1<<10), // monster is perma-confused,
M_BATTY = (1<<11), // monster is batty
M_SPLITS = (1<<12), // monster can split
M_AMPHIBIOUS = (1<<13), // monster can swim in water,
M_THICK_SKIN = (1<<14), // monster has more effective AC,
M_HUMANOID = (1<<15), // for Glamour
M_COLD_BLOOD = (1<<16), // susceptible to cold
M_WARM_BLOOD = (1<<17), // no effect currently
M_REGEN = (1<<18), // regenerates quickly
M_BURROWS = (1<<19), // monster digs through rock
M_EVIL = (1<<20), // monster vulnerable to holy spells
M_UNIQUE = (1<<21), // monster is a unique
M_ACID_SPLASH = (1<<22), // Passive acid splash when hit.
M_ARCHER = (1<<23), // gets various archery boosts
M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells?
M_NO_SKELETON = (1<<29), // boneless corpses
M_NO_EXP_GAIN = (1<<31) // worth 0 xp
};
enum mon_event_type
{
ME_EVAL, // 0, evaluate monster AI state
ME_DISTURB, // noisy
ME_ANNOY, // annoy at range
ME_ALERT, // alert to presence
ME_WHACK, // physical attack
ME_SHOT, // attack at range
ME_SCARE, // frighten monster
ME_CORNERED // cannot flee
};
enum mon_intel_type // Must be in increasing intelligence order
{
I_PLANT = 0,
I_INSECT,
I_ANIMAL,
I_NORMAL,
I_HIGH
};
// order of these is important:
enum mon_itemuse_type
{
MONUSE_NOTHING,
MONUSE_EATS_ITEMS,
MONUSE_OPEN_DOORS,
MONUSE_STARTING_EQUIPMENT,
MONUSE_WEAPONS_ARMOUR,
MONUSE_MAGIC_ITEMS
};
// now saved in an unsigned long.
enum mon_resist_flags
{
MR_NO_FLAGS = 0,
// resistances
// Notes:
// - negative energy is mostly handled via mons_has_life_force()
// - acid is handled mostly by genus (jellies) plus non-living
// - asphyx-resistance replaces hellfrost resistance.
MR_RES_ELEC = (1<< 0),
MR_RES_POISON = (1<< 1),
MR_RES_FIRE = (1<< 2),
MR_RES_HELLFIRE = (1<< 3),
MR_RES_COLD = (1<< 4),
MR_RES_ASPHYX = (1<< 5),
MR_RES_ACID = (1<< 6),
// vulnerabilities
MR_VUL_ELEC = (1<< 7),
MR_VUL_POISON = (1<< 8),
MR_VUL_FIRE = (1<< 9),
MR_VUL_COLD = (1<<10),
// melee armour resists/vulnerabilities
// XXX: how to do combos (bludgeon/slice, bludgeon/pierce)
MR_RES_PIERCE = (1<<11),
MR_RES_SLICE = (1<<12),
MR_RES_BLUDGEON = (1<<13),
MR_VUL_PIERCE = (1<<14),
MR_VUL_SLICE = (1<<15),
MR_VUL_BLUDGEON = (1<<16)
};
enum shout_type
{
S_SILENT, // silent
S_SHOUT, // shout
S_BARK, // bark
S_SHOUT2, // shout twice (e.g. two-headed ogres)
S_ROAR, // roar
S_SCREAM, // scream
S_BELLOW, // bellow (?)
S_SCREECH, // screech
S_BUZZ, // buzz
S_MOAN, // moan
S_WHINE, // irritating whine (mosquito)
S_CROAK, // frog croak
S_GROWL, // for bears
S_HISS, // for snakes and lizards
// Loudness setting for shouts that are only defined in dat/shout.txt
S_VERY_SOFT,
S_SOFT,
S_NORMAL,
S_LOUD,
S_VERY_LOUD,
NUM_SHOUTS,
S_RANDOM
};
enum zombie_size_type
{
Z_NOZOMBIE,
Z_SMALL,
Z_BIG
};
* called from: acr
* *********************************************************************** */
void disarm_trap(struct dist &disa);
void remove_net_from( monsters *mon );
void free_self_from_net( bool damage_net = true );
// last updated 12may2000 {dlb}
/* ***********************************************************************
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
unsigned char terrain );
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: acr - misc
* *********************************************************************** */
void handle_traps(char trt, int i, bool trap_known);
int get_trapping_net(int x, int y, bool trapped = true);
void mark_net_trapping(int x, int y);
void monster_caught_in_net(monsters *mon, bolt &pbolt);
void player_caught_in_net(void);
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells3
* *********************************************************************** */
int trap_at_xy(int which_x, int which_y);
// last updated 3jun2000 {dlb}
/* ***********************************************************************
* called from: acr - misc - mstuff2 - spells2 - spells3
* *********************************************************************** */
dungeon_feature_type trap_category(trap_type type);
int trap_at_xy(int x, int y);
trap_type trap_type_at_xy(int x, int y);
bool grid_is_wall(dungeon_feature_type grid);
bool grid_is_opaque(dungeon_feature_type grid);
bool grid_is_solid(dungeon_feature_type grid);
bool grid_is_stone_stair(dungeon_feature_type grid);
bool grid_is_rock_stair(dungeon_feature_type grid);
bool grid_is_solid(int x, int y);
bool grid_is_solid(const coord_def &c);
bool grid_is_trap(dungeon_feature_type grid);
command_type grid_stair_direction(dungeon_feature_type grid);
bool grid_sealable_portal(dungeon_feature_type grid);
bool grid_is_portal(dungeon_feature_type grid);
bool grid_is_water(dungeon_feature_type grid);
bool grid_is_watery(dungeon_feature_type grid);
god_type grid_altar_god( dungeon_feature_type grid );
dungeon_feature_type altar_for_god( god_type god );
bool grid_is_branch_stairs( dungeon_feature_type grid );
int grid_secret_door_appearance( int gx, int gy );
bool grid_destroys_items( dungeon_feature_type grid );
bool level_type_exits_up(level_area_type type);
bool level_type_exits_down(level_area_type type);
// Terrain changed under 'pos', perform necessary effects.
void dungeon_terrain_changed(const coord_def &pos,
dungeon_feature_type feat = DNGN_UNSEEN,
bool affect_player = true,
bool preserve_features = false,
bool preserve_items = false);
unsigned short get_packed_place( branch_type branch, int subdepth,
level_area_type level_type );
int place_branch(unsigned short place);
int place_depth(unsigned short place);
std::string short_place_name(unsigned short place);
std::string short_place_name(level_id id);
std::string place_name( unsigned short place, bool long_name = false,
bool include_number = true );
// Prepositional form of branch level name. For example, "in the
// Abyss" or "on level 3 of the Main Dungeon".
std::string prep_branch_level_name(unsigned short packed_place);
std::string prep_branch_level_name();
// Get displayable depth in the current branch, given the absolute
// depth.
int subdungeon_depth(branch_type branch, int depth);
// Get absolute depth given the displayable depth in the branch.
int absdungeon_depth(branch_type branch, int subdepth);
// Get displayable depth in the current branch.
int player_branch_depth();
bool single_level_branch(branch_type branch);
//////////////////////////////////////////////////////////////////////
#include "macro.h"
#include "makeitem.h"
#include "mapmark.h"
#include "monplace.h"
#include "message.h"
bool grid_is_wall( dungeon_feature_type grid )
{
return (grid == DNGN_ROCK_WALL
|| grid == DNGN_STONE_WALL
|| grid == DNGN_METAL_WALL
|| grid == DNGN_GREEN_CRYSTAL_WALL
|| grid == DNGN_WAX_WALL
|| grid == DNGN_PERMAROCK_WALL);
}
bool grid_is_stone_stair(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_STONE_STAIRS_UP_I:
case DNGN_STONE_STAIRS_UP_II:
case DNGN_STONE_STAIRS_UP_III:
case DNGN_STONE_STAIRS_DOWN_I:
case DNGN_STONE_STAIRS_DOWN_II:
case DNGN_STONE_STAIRS_DOWN_III:
return (true);
default:
return (false);
}
}
bool grid_is_rock_stair(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_ROCK_STAIRS_UP:
case DNGN_ROCK_STAIRS_DOWN:
return (true);
default:
return (false);
}
}
bool grid_sealable_portal(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_ENTER_HELL:
case DNGN_ENTER_ABYSS:
case DNGN_ENTER_PANDEMONIUM:
case DNGN_ENTER_LABYRINTH:
case DNGN_ENTER_PORTAL_VAULT:
return (true);
default:
return (false);
}
}
bool grid_is_portal(dungeon_feature_type grid)
{
return (grid == DNGN_ENTER_PORTAL_VAULT || grid == DNGN_EXIT_PORTAL_VAULT);
}
command_type grid_stair_direction(dungeon_feature_type grid)
{
switch (grid)
{
case DNGN_STONE_STAIRS_UP_I:
case DNGN_STONE_STAIRS_UP_II:
case DNGN_STONE_STAIRS_UP_III:
case DNGN_ROCK_STAIRS_UP:
case DNGN_RETURN_FROM_ORCISH_MINES:
case DNGN_RETURN_FROM_HIVE:
case DNGN_RETURN_FROM_LAIR:
case DNGN_RETURN_FROM_SLIME_PITS:
case DNGN_RETURN_FROM_VAULTS:
case DNGN_RETURN_FROM_CRYPT:
case DNGN_RETURN_FROM_HALL_OF_BLADES:
case DNGN_RETURN_FROM_ZOT:
case DNGN_RETURN_FROM_TEMPLE:
case DNGN_RETURN_FROM_SNAKE_PIT:
case DNGN_RETURN_FROM_ELVEN_HALLS:
case DNGN_RETURN_FROM_TOMB:
case DNGN_RETURN_FROM_SWAMP:
case DNGN_RETURN_FROM_SHOALS:
case DNGN_RETURN_RESERVED_2:
case DNGN_RETURN_RESERVED_3:
case DNGN_RETURN_RESERVED_4:
case DNGN_ENTER_SHOP:
case DNGN_EXIT_HELL:
case DNGN_EXIT_PORTAL_VAULT:
return (CMD_GO_UPSTAIRS);
case DNGN_ENTER_PORTAL_VAULT:
case DNGN_ENTER_HELL:
case DNGN_ENTER_LABYRINTH:
case DNGN_STONE_STAIRS_DOWN_I:
case DNGN_STONE_STAIRS_DOWN_II:
case DNGN_STONE_STAIRS_DOWN_III:
case DNGN_ROCK_STAIRS_DOWN:
case DNGN_ENTER_DIS:
case DNGN_ENTER_GEHENNA:
case DNGN_ENTER_COCYTUS:
case DNGN_ENTER_TARTARUS:
case DNGN_ENTER_ABYSS:
case DNGN_EXIT_ABYSS:
case DNGN_ENTER_PANDEMONIUM:
case DNGN_EXIT_PANDEMONIUM:
case DNGN_TRANSIT_PANDEMONIUM:
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:
case DNGN_ENTER_RESERVED_2:
case DNGN_ENTER_RESERVED_3:
case DNGN_ENTER_RESERVED_4:
return (CMD_GO_DOWNSTAIRS);
default:
return (CMD_NO_CMD);
}
}
bool grid_is_opaque( dungeon_feature_type grid )
{
return (grid < DNGN_MINSEE && grid != DNGN_ORCISH_IDOL);
}
bool grid_is_solid( dungeon_feature_type grid )
{
return (grid < DNGN_MINMOVE);
}
bool grid_is_solid( int x, int y )
{
return (grid_is_solid(grd[x][y]));
}
bool grid_is_solid(const coord_def &c)
{
return (grid_is_solid(grd(c)));
}
bool grid_is_trap(dungeon_feature_type grid)
{
return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
|| grid == DNGN_TRAP_III);
}
bool grid_is_water( dungeon_feature_type grid )
{
return (grid == DNGN_SHALLOW_WATER || grid == DNGN_DEEP_WATER);
}
bool grid_is_watery( dungeon_feature_type grid )
{
return (grid_is_water(grid) || grid == DNGN_BLUE_FOUNTAIN);
}
bool grid_destroys_items( dungeon_feature_type grid )
{
return (grid == DNGN_LAVA || grid == DNGN_DEEP_WATER);
}
// returns 0 if grid is not an altar, else it returns the GOD_* type
god_type grid_altar_god( dungeon_feature_type grid )
{
if (grid >= DNGN_ALTAR_ZIN && grid <= DNGN_ALTAR_BEOGH)
return (static_cast<god_type>( grid - DNGN_ALTAR_ZIN + 1 ));
return (GOD_NO_GOD);
}
// returns DNGN_FLOOR for non-gods, otherwise returns the altar for
// the god.
dungeon_feature_type altar_for_god( god_type god )
{
if (god == GOD_NO_GOD || god >= NUM_GODS)
return (DNGN_FLOOR); // Yeah, lame. Tell me about it.
return static_cast<dungeon_feature_type>(DNGN_ALTAR_ZIN + god - 1);
}
bool grid_is_branch_stairs( dungeon_feature_type grid )
{
return ((grid >= DNGN_ENTER_ORCISH_MINES && grid <= DNGN_ENTER_RESERVED_4)
|| (grid >= DNGN_ENTER_DIS && grid <= DNGN_ENTER_TARTARUS));
}
int grid_secret_door_appearance( int gx, int gy )
{
int ret = DNGN_FLOOR;
for (int dx = -1; dx <= 1; dx++)
{
for (int dy = -1; dy <= 1; dy++)
{
// only considering orthogonal grids
if ((abs(dx) + abs(dy)) % 2 == 0)
continue;
const dungeon_feature_type targ = grd[gx + dx][gy + dy];
if (!grid_is_wall( targ ))
continue;
if (ret == DNGN_FLOOR)
ret = targ;
else if (ret != targ)
ret = ((ret < targ) ? ret : targ);
}
}
return ((ret == DNGN_FLOOR) ? DNGN_ROCK_WALL
: ret);
}
const char *grid_item_destruction_message( dungeon_feature_type grid )
{
return grid == DNGN_DEEP_WATER? "You hear a splash."
: grid == DNGN_LAVA ? "You hear a sizzling splash."
: "You hear a crunching noise.";
}
// Returns true if exits from this type of level involve going upstairs.
bool level_type_exits_up(level_area_type type)
{
return (type == LEVEL_LABYRINTH || type == LEVEL_PORTAL_VAULT);
}
bool level_type_exits_down(level_area_type type)
{
return (type == LEVEL_PANDEMONIUM || type == LEVEL_ABYSS);
}
static coord_def dgn_find_nearest_square(
const coord_def &pos,
bool (*acceptable)(const coord_def &),
bool (*traversable)(const coord_def &) = NULL)
{
memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
std::list<coord_def> points[2];
int iter = 0;
points[iter].push_back(pos);
while (!points[iter].empty())
{
for (std::list<coord_def>::iterator i = points[iter].begin();
i != points[iter].end(); ++i)
{
const coord_def &p = *i;
if (p != pos && acceptable(p))
return (p);
travel_point_distance[p.x][p.y] = 1;
for (int yi = -1; yi <= 1; ++yi)
{
for (int xi = -1; xi <= 1; ++xi)
{
if (!xi && !yi)
continue;
const coord_def np = p + coord_def(xi, yi);
if (!in_bounds(np) || travel_point_distance[np.x][np.y])
continue;
if (traversable && !traversable(np))
continue;
points[!iter].push_back(np);
}
}
}
points[iter].clear();
iter = !iter;
}
coord_def unfound;
return (unfound);
}
static bool item_safe_square(const coord_def &pos)
{
const dungeon_feature_type feat = grd(pos);
return (is_traversable(feat) && !grid_destroys_items(feat));
}
// Moves an item on the floor to the nearest adjacent floor-space.
static bool dgn_shift_item(const coord_def &pos, item_def &item)
{
const coord_def np = dgn_find_nearest_square(pos, item_safe_square);
if (in_bounds(np) && np != pos)
{
int index = item.index();
move_item_to_grid(&index, np.x, np.y);
return (true);
}
return (false);
}
static bool is_critical_feature(dungeon_feature_type feat)
{
return (grid_stair_direction(feat) != CMD_NO_CMD
|| grid_altar_god(feat) != GOD_NO_GOD);
}
static bool is_feature_shift_target(const coord_def &pos)
{
return (grd(pos) == DNGN_FLOOR && !dungeon_events.has_listeners_at(pos));
}
static bool dgn_shift_feature(const coord_def &pos)
{
const dungeon_feature_type dfeat = grd(pos);
if (!is_critical_feature(dfeat) && !env.markers.find(pos, MAT_ANY))
return (false);
const coord_def dest =
dgn_find_nearest_square(pos, is_feature_shift_target);
if (in_bounds(dest) && dest != pos)
{
grd(dest) = dfeat;
if (dfeat == DNGN_ENTER_SHOP)
{
if (shop_struct *s = get_shop(pos.x, pos.y))
{
s->x = dest.x;
s->y = dest.y;
}
}
env.markers.move(pos, dest);
dungeon_events.move_listeners(pos, dest);
}
return (true);
}
static void dgn_check_terrain_items(const coord_def &pos, bool preserve_items)
{
const dungeon_feature_type grid = grd(pos);
if (grid_is_solid(grid) || grid_destroys_items(grid))
{
int item = igrd(pos);
bool did_destroy = false;
while (item != NON_ITEM)
{
const int curr = item;
item = mitm[item].link;
// Game-critical item.
if (preserve_items || item_is_critical(mitm[curr]))
dgn_shift_item(pos, mitm[curr]);
else
{
destroy_item(curr);
did_destroy = true;
}
}
if (did_destroy && player_can_hear(pos))
mprf(MSGCH_SOUND, grid_item_destruction_message(grid));
}
}
static void dgn_check_terrain_monsters(const coord_def &pos)
{
const int mindex = mgrd(pos);
if (mindex != NON_MONSTER)
{
monsters *mons = &menv[mindex];
if (grid_is_solid(grd(pos)))
monster_teleport(mons, true, false);
else
mons_check_pool(mons, KILL_MISC, -1);
}
}
void dungeon_terrain_changed(const coord_def &pos,
dungeon_feature_type nfeat,
bool affect_player,
bool preserve_features,
bool preserve_items)
{
if (nfeat != DNGN_UNSEEN)
{
if (preserve_features)
dgn_shift_feature(pos);
unnotice_feature(level_pos(level_id::current(), pos));
grd(pos) = nfeat;
env.grid_colours(pos) = BLACK;
if (is_notable_terrain(nfeat) && see_grid(pos))
seen_notable_thing(nfeat, pos.x, pos.y);
}
dgn_check_terrain_items(pos, preserve_items);
if (affect_player && pos == you.pos())
{
if (!grid_is_solid(grd(pos)))
{
if (!you.flies())
move_player_to_grid(pos.x, pos.y, false, true, false);
}
else
you_teleport_now(true, false);
}
dgn_check_terrain_monsters(pos);
}
// returns the number of a net on a given square
// if trapped only stationary ones are counted
// otherwise the first net found is returned
int get_trapping_net(int x, int y, bool trapped)
{
int net, next;
for (net = igrd[x][y]; net != NON_ITEM; net = next)
{
next = mitm[net].link;
if (mitm[net].base_type == OBJ_MISSILES
&& mitm[net].sub_type == MI_THROWING_NET
&& (!trapped || item_is_stationary(mitm[net])))
{
return (net);
}
}
return (NON_ITEM);
}
// if there are more than one net on this square
// split off one of them for checking/setting values
static void maybe_split_nets(item_def &item, int x, int y)
{
if (item.quantity == 1)
{
set_item_stationary(item);
return;
}
item_def it;
it.base_type = item.base_type;
it.sub_type = item.sub_type;
it.plus = item.plus;
it.plus2 = item.plus2;
it.flags = item.flags;
it.special = item.special;
it.quantity = --item.quantity;
item_colour(it);
item.quantity = 1;
set_item_stationary(item);
copy_item_to_grid( it, x, y );
}
void mark_net_trapping(int x, int y)
{
int net = get_trapping_net(x,y);
if (net == NON_ITEM)
{
net = get_trapping_net(x,y, false);
if (net != NON_ITEM)
maybe_split_nets(mitm[net], x, y);
}
}
void monster_caught_in_net(monsters *mon, bolt &pbolt)
{
if (mon->body_size(PSIZE_BODY) >= SIZE_GIANT)
return;
if (mons_is_insubstantial(mon->type))
{
if (mons_near(mon) && player_monster_visible(mon))
mprf("The net passes right through %s!", mon->name(DESC_NOCAP_THE).c_str());
return;
}
const monsters* mons = static_cast<const monsters*>(mon);
bool mon_flies = mons->flies();
if (mon_flies && !mons_is_confused(mons))
{
simple_monster_message(mon, " darts out from under the net!");
return;
}
if (mons->type == MONS_OOZE || mons->type == MONS_PULSATING_LUMP)
{
simple_monster_message(mon, " oozes right through the net!");
return;
}
if (!mons_is_caught(mon) && mon->add_ench(ENCH_HELD))
{
if (mons_near(mon) && !player_monster_visible(mon))
mpr("Something gets caught in the net!");
else
simple_monster_message(mon, " is caught in the net!");
if (mon_flies)
{
simple_monster_message(mon, " falls like a stone!");
mons_check_pool(mon, pbolt.killer(), pbolt.beam_source);
}
}
}
void player_caught_in_net()
{
if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
return;
if (you.flies() && !you.confused())
{
mpr("You dart out from under the net!");
return;
}
if (!you.attribute[ATTR_HELD])
{
you.attribute[ATTR_HELD] = 10;
mpr("You become entangled in the net!");
// I guess levitation works differently, keeping both you
// and the net hovering above the floor
if (you.flies())
{
mpr("You fall like a stone!");
fall_into_a_pool(you.x_pos, you.y_pos, false, grd[you.x_pos][you.y_pos]);
}
}
}
}
static void dart_trap(bool trap_known, int trapped, bolt &pbolt, bool poison)
{
int damage_taken = 0;
int trap_hit, your_dodge;
if (one_chance_in(5) || (trap_known && !one_chance_in(4)))
{
mprf( "You avoid triggering a%s trap.", pbolt.name.c_str() );
return;
}
if (you.equip[EQ_SHIELD] != -1 && one_chance_in(3))
exercise( SK_SHIELDS, 1 );
std::string msg = "A" + pbolt.name + " shoots out and ";
if (random2( 20 + 5 * you.shield_blocks * you.shield_blocks )
< player_shield_class())
{
you.shield_blocks++;
msg += "hits your shield.";
mpr(msg.c_str());
}
else
{
// note that this uses full ( not random2limit(foo,40) )
// player_evasion.
trap_hit = (20 + (you.your_level * 2)) * random2(200) / 100;
your_dodge = player_evasion() + random2(you.dex) / 3
- 2 + (you.duration[DUR_REPEL_MISSILES] * 10);
if (trap_hit >= your_dodge && you.duration[DUR_DEFLECT_MISSILES] == 0)
{
msg += "hits you!";
mpr(msg.c_str());
if (poison && random2(100) < 50 - (3 * player_AC()) / 2
&& !player_res_poison())
{
poison_player( 1 + random2(3) );
}
damage_taken = roll_dice( pbolt.damage );
damage_taken -= random2( player_AC() + 1 );
if (damage_taken > 0)
ouch( damage_taken, 0, KILLED_BY_TRAP, pbolt.name.c_str() );
}
else
{
msg += "misses you.";
mpr(msg.c_str());
}
if (player_light_armour(true) && coinflip())
exercise( SK_DODGING, 1 );
}
pbolt.target_x = you.x_pos;
pbolt.target_y = you.y_pos;
if (coinflip())
itrap( pbolt, trapped );
} // end dart_trap()
//
// itrap takes location from target_x, target_y of bolt strcture.
//
void itrap( struct bolt &pbolt, int trapped )
{
object_class_type base_type = OBJ_MISSILES;
int sub_type = MI_DART;
switch (env.trap[trapped].type)
{
case TRAP_DART:
base_type = OBJ_MISSILES;
sub_type = MI_DART;
break;
case TRAP_ARROW:
base_type = OBJ_MISSILES;
sub_type = MI_ARROW;
break;
case TRAP_BOLT:
base_type = OBJ_MISSILES;
sub_type = MI_BOLT;
break;
case TRAP_SPEAR:
base_type = OBJ_WEAPONS;
sub_type = WPN_SPEAR;
break;
case TRAP_AXE:
base_type = OBJ_WEAPONS;
sub_type = WPN_HAND_AXE;
break;
case TRAP_NEEDLE:
base_type = OBJ_MISSILES;
sub_type = MI_NEEDLE;
break;
case TRAP_NET:
base_type = OBJ_MISSILES;
sub_type = MI_THROWING_NET;
break;
default:
return;
}
trap_item( base_type, sub_type, pbolt.target_x, pbolt.target_y );
return;
} // end itrap()
void handle_traps(char trt, int i, bool trap_known)
{
struct bolt beam;
switch (trt)
{
case TRAP_DART:
beam.name = " dart";
beam.damage = dice_def( 1, 4 + (you.your_level / 2) );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_NEEDLE:
beam.name = " needle";
beam.damage = dice_def( 1, 0 );
dart_trap(trap_known, i, beam, true);
break;
case TRAP_ARROW:
beam.name = "n arrow";
beam.damage = dice_def( 1, 7 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_BOLT:
beam.name = " bolt";
beam.damage = dice_def( 1, 13 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_SPEAR:
beam.name = " spear";
beam.damage = dice_def( 1, 10 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_AXE:
beam.name = "n axe";
beam.damage = dice_def( 1, 15 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_TELEPORT:
mpr("You enter a teleport trap!");
if (scan_randarts(RAP_PREVENT_TELEPORTATION))
mpr("You feel a weird sense of stasis.");
else
you_teleport_now( true );
break;
case TRAP_AMNESIA:
mpr("You feel momentarily disoriented.");
if (!wearing_amulet(AMU_CLARITY))
forget_map(random2avg(100, 2));
break;
case TRAP_BLADE:
if (trap_known && one_chance_in(3))
mpr("You avoid triggering a blade trap.");
else if (random2limit(player_evasion(), 40)
+ (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 8)
{
mpr("A huge blade swings just past you!");
}
else
{
mpr("A huge blade swings out and slices into you!");
ouch( (you.your_level * 2) + random2avg(29, 2)
- random2(1 + player_AC()), 0, KILLED_BY_TRAP, " blade" );
}
break;
case TRAP_NET:
if (trap_known && one_chance_in(3))
mpr("A net swings high above you.");
else
{
if (random2limit(player_evasion(), 40)
+ (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 12)
{
mpr("A net drops to the ground!");
}
else
{
mpr("A large net falls onto you!");
player_caught_in_net();
}
trap_item( OBJ_MISSILES, MI_THROWING_NET, env.trap[i].x, env.trap[i].y );
if (you.attribute[ATTR_HELD])
mark_net_trapping(you.x_pos, you.y_pos);
grd[env.trap[i].x][env.trap[i].y] = DNGN_FLOOR;
env.trap[i].type = TRAP_UNASSIGNED;
}
break;
case TRAP_ZOT:
default:
mpr((trap_known) ? "You enter the Zot trap."
: "Oh no! You have blundered into a Zot trap!");
miscast_effect( SPTYP_RANDOM, random2(30) + you.your_level,
75 + random2(100), 3, "a Zot trap" );
break;
}
learned_something_new(TUT_SEEN_TRAP, you.x_pos, you.y_pos);
} // end handle_traps()
void disarm_trap( struct dist &disa )
{
if (you.duration[DUR_BERSERKER])
{
canned_msg(MSG_TOO_BERSERK);
return;
}
int i, j;
for (i = 0; i < MAX_TRAPS; i++)
{
if (env.trap[i].x == you.x_pos + disa.dx
&& env.trap[i].y == you.y_pos + disa.dy)
{
break;
}
if (i == MAX_TRAPS - 1)
{
mpr("Error - couldn't find that trap.");
return;
}
}
if (trap_category(env.trap[i].type) == DNGN_TRAP_MAGICAL)
{
mpr("You can't disarm that trap.");
return;
}
if (random2(you.skills[SK_TRAPS_DOORS] + 2) <= random2(you.your_level + 5))
{
mpr("You failed to disarm the trap.");
you.turn_is_over = true;
if (random2(you.dex) > 5 + random2(5 + you.your_level))
exercise(SK_TRAPS_DOORS, 1 + random2(you.your_level / 5));
else
{
if (env.trap[i].type == TRAP_NET &&
(env.trap[i].x != you.x_pos || env.trap[i].y != you.y_pos))
{
if (coinflip())
return;
mpr("You stumble into the trap!");
move_player_to_grid( env.trap[i].x, env.trap[i].y, true, false, true);
}
else
handle_traps(env.trap[i].type, i, false);
if (coinflip())
exercise(SK_TRAPS_DOORS, 1);
}
return;
}
mpr("You have disarmed the trap.");
struct bolt beam;
beam.target_x = you.x_pos + disa.dx;
beam.target_y = you.y_pos + disa.dy;
if (env.trap[i].type == TRAP_NET)
trap_item( OBJ_MISSILES, MI_THROWING_NET, beam.target_x, beam.target_y );
else if (env.trap[i].type != TRAP_BLADE
&& trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL)
{
const int num_to_make = 10 + random2(you.skills[SK_TRAPS_DOORS]);
for (j = 0; j < num_to_make; j++)
{
// places items (eg darts), which will automatically stack
itrap(beam, i);
}
}
grd[you.x_pos + disa.dx][you.y_pos + disa.dy] = DNGN_FLOOR;
env.trap[i].type = TRAP_UNASSIGNED;
you.turn_is_over = true;
// reduced from 5 + random2(5)
exercise(SK_TRAPS_DOORS, 1 + random2(5) + (you.your_level / 5));
} // end disarm_trap()
// attempts to take a net off a given monster
// Do not expect gratitude for this!
// ----------------------------------
void remove_net_from(monsters *mon)
{
you.turn_is_over = true;
int net = get_trapping_net(mon->x, mon->y);
if (net == NON_ITEM)
{
mon->del_ench(ENCH_HELD, true);
return;
}
// factor in whether monster is paralysed or invisible
int paralys = 0;
if (mons_is_paralysed(mon)) // makes this easier
paralys = random2(5);
int invis = 0;
if (!player_monster_visible(mon)) // makes this harder
invis = 3 + random2(5);
bool net_destroyed = false;
if ( random2(you.skills[SK_TRAPS_DOORS] + 2) + paralys
<= random2( 2*mon->body_size(PSIZE_BODY) + 3 ) + invis)
{
if (one_chance_in(you.skills[SK_TRAPS_DOORS] + you.dex/2))
{
mitm[net].plus--;
mpr("You tear at the net.");
if (mitm[net].plus < -7)
{
mpr("Whoops! The net comes apart in your hands!");
mon->del_ench(ENCH_HELD, true);
destroy_item(net);
net_destroyed = true;
}
}
if (!net_destroyed)
{
if (player_monster_visible(mon))
{
mprf("You fail to remove the net from %s.",
mon->name(DESC_NOCAP_THE).c_str());
}
else
mpr("You fail to remove the net.");
}
if (random2(you.dex) > 5 + random2( 2*mon->body_size(PSIZE_BODY) ))
exercise(SK_TRAPS_DOORS, 1 + random2(mon->body_size(PSIZE_BODY)/2));
return;
}
mon->del_ench(ENCH_HELD, true);
remove_item_stationary(mitm[net]);
if (player_monster_visible(mon))
mprf("You free %s.", mon->name(DESC_NOCAP_THE).c_str());
else
mpr("You loosen the net.");
if (net == NON_ITEM) // really shouldn't happen!
{
you.attribute[ATTR_HELD] = 0;
return;
}
int hold = mitm[net].plus;
if (damage_net)
{
mpr("You struggle against the net.");
int damage = 1;
// extra damage for cutting weapons
if (you.equip[EQ_WEAPON] != -1
&& can_cut_meat(you.inv[you.equip[EQ_WEAPON]]))
{
damage++;
}
if (you.body_size(PSIZE_BODY) > SIZE_MEDIUM)
damage++;
if (hold < 0 && !one_chance_in(-hold/2))
damage++;
if (you.duration[DUR_BERSERKER])
damage *= 2;
mitm[net].plus -= damage;
if (mitm[net].plus < -7)
{
mpr("You rip the net and break free!");
dec_mitm_item_quantity( net, 1 );
you.attribute[ATTR_HELD] = 0;
return;
}
}
else // you try to escape
{
mpr("You struggle to escape from the net.");
you.attribute[ATTR_HELD]--;
if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM)
you.attribute[ATTR_HELD]--;
if (hold < 0 && !one_chance_in(-hold/2))
you.attribute[ATTR_HELD]--;
if (you.attribute[ATTR_HELD] <= 0)
{
mpr("You break free from the net!");
you.attribute[ATTR_HELD] = 0;
remove_item_stationary(mitm[net]);
return;
}
}
}
// returns true if we manage to scramble free.
bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
unsigned char terrain )
{
bool escape = false;
FixedVector< char, 2 > empty;
if (you.species == SP_MERFOLK && terrain == DNGN_DEEP_WATER)
{
// These can happen when we enter deep water directly -- bwr
merfolk_start_swimming();
return (false);
}
// sanity check
if (terrain != DNGN_LAVA && beogh_water_walk())
return (false);
mprf("You fall into the %s!",
(terrain == DNGN_LAVA) ? "lava" :
(terrain == DNGN_DEEP_WATER) ? "water"
: "programming rift");
more();
mesclr();
if (terrain == DNGN_LAVA)
{
const int resist = player_res_fire();
if (resist <= 0)
{
mpr( "The lava burns you to a cinder!" );
ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
}
else
{
// should boost # of bangs per damage in the future {dlb}
mpr( "The lava burns you!" );
ouch( (10 + roll_dice(2,50)) / resist, 0, KILLED_BY_LAVA );
}
expose_player_to_element( BEAM_LAVA, 14 );
}
// a distinction between stepping and falling from you.duration[DUR_LEVITATION]
// prevents stepping into a thin stream of lava to get to the other side.
if (scramble())
{
if (allow_shift)
{
if (empty_surrounds( you.x_pos, you.y_pos, DNGN_FLOOR, 1,
false, empty ))
{
escape = true;
}
else
{
escape = false;
}
}
else
{
// back out the way we came in, if possible
if (grid_distance( you.x_pos, you.y_pos, entry_x, entry_y ) == 1
&& (entry_x != empty[0] || entry_y != empty[1])
&& mgrd[entry_x][entry_y] == NON_MONSTER)
{
escape = true;
empty[0] = entry_x;
empty[1] = entry_y;
}
else // zero or two or more squares away, with no way back
{
escape = false;
}
}
}
else
{
mpr("You try to escape, but your burden drags you down!");
}
if (escape)
{
const coord_def pos(empty[0], empty[1]);
if (in_bounds(pos) && !is_grid_dangerous(grd(pos)))
{
mpr("You manage to scramble free!");
move_player_to_grid( empty[0], empty[1], false, false, true );
if (terrain == DNGN_LAVA)
expose_player_to_element( BEAM_LAVA, 14 );
return (true);
}
}
mpr("You drown...");
if (terrain == DNGN_LAVA)
ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
else if (terrain == DNGN_DEEP_WATER)
ouch( INSTANT_DEATH, 0, KILLED_BY_WATER );
return (false);
} // end fall_into_a_pool()
bool trap_item(object_class_type base_type, char sub_type,
char beam_x, char beam_y)
{
item_def item;
item.base_type = base_type;
item.sub_type = sub_type;
item.plus = 0;
item.plus2 = 0;
item.flags = 0;
item.special = 0;
item.quantity = 1;
if (base_type == OBJ_MISSILES)
{
if (sub_type == MI_NEEDLE)
set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
else
set_item_ego_type( item, OBJ_MISSILES, SPMSL_NORMAL );
}
else
{
set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
}
item_colour(item);
if (igrd[beam_x][beam_y] != NON_ITEM)
{
if (items_stack( item, mitm[ igrd[beam_x][beam_y] ] ))
{
inc_mitm_item_quantity( igrd[beam_x][beam_y], 1 );
return (false);
}
// don't want to go overboard here. Will only generate up to three
// separate trap items, or less if there are other items present.
if (mitm[ igrd[beam_x][beam_y] ].link != NON_ITEM
&& (item.base_type != OBJ_MISSILES || item.sub_type != MI_THROWING_NET))
{
if (mitm[ mitm[ igrd[beam_x][beam_y] ].link ].link != NON_ITEM)
return (false);
}
} // end of if igrd != NON_ITEM
return (!copy_item_to_grid( item, beam_x, beam_y, 1 ));
} // end trap_item()
// returns appropriate trap symbol for a given trap type {dlb}
dungeon_feature_type trap_category(trap_type type)
{
switch (type)
{
case TRAP_TELEPORT:
case TRAP_AMNESIA:
case TRAP_ZOT:
return (DNGN_TRAP_MAGICAL);
case TRAP_DART:
case TRAP_ARROW:
case TRAP_SPEAR:
case TRAP_AXE:
case TRAP_BLADE:
case TRAP_BOLT:
case TRAP_NEEDLE:
case TRAP_NET:
default: // what *would* be the default? {dlb}
return (DNGN_TRAP_MECHANICAL);
}
} // end trap_category()
// returns index of the trap for a given (x,y) coordinate pair {dlb}
int trap_at_xy(int which_x, int which_y)
{
for (int which_trap = 0; which_trap < MAX_TRAPS; which_trap++)
{
if (env.trap[which_trap].x == which_x &&
env.trap[which_trap].y == which_y &&
env.trap[which_trap].type != TRAP_UNASSIGNED)
{
return (which_trap);
}
}
// no idea how well this will be handled elsewhere: {dlb}
return (-1);
} // end trap_at_xy()
trap_type trap_type_at_xy(int x, int y)
{
const int idx = trap_at_xy(x, y);
return (idx == -1? NUM_TRAPS : env.trap[idx].type);
}
// Do not attempt to use level_id if level_type != LEVEL_DUNGEON
std::string short_place_name(level_id id)
{
return id.describe();
}
int place_branch(unsigned short place)
{
const unsigned branch = (unsigned) ((place >> 8) & 0xFF);
const int lev = place & 0xFF;
return lev == 0xFF? -1 : (int) branch;
}
int place_depth(unsigned short place)
{
const int lev = place & 0xFF;
return lev == 0xFF? -1 : lev;
}
unsigned short get_packed_place( branch_type branch, int subdepth,
level_area_type level_type )
{
unsigned short place = (unsigned short)
( (static_cast<int>(branch) << 8) | (subdepth & 0xFF) );
if (level_type != LEVEL_DUNGEON)
place = (unsigned short) ( (static_cast<int>(level_type) << 8) | 0xFF );
return place;
}
unsigned short get_packed_place()
{
return get_packed_place( you.where_are_you,
subdungeon_depth(you.where_are_you, you.your_level),
you.level_type );
}
bool single_level_branch( branch_type branch )
{
return
branch >= 0 && branch < NUM_BRANCHES
&& branches[branch].depth == 1;
}
std::string place_name( unsigned short place, bool long_name,
bool include_number )
{
unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
int lev = place & 0xFF;
std::string result;
if (lev == 0xFF)
{
switch (branch)
{
case LEVEL_ABYSS:
return ( long_name ? "The Abyss" : "Abyss" );
case LEVEL_PANDEMONIUM:
return ( long_name ? "Pandemonium" : "Pan" );
case LEVEL_LABYRINTH:
return ( long_name ? "a Labyrinth" : "Lab" );
case LEVEL_PORTAL_VAULT:
return ( long_name ? "a Portal Chamber" : "Port" );
default:
return ( long_name ? "Buggy Badlands" : "Bug" );
}
}
result = (long_name ?
branches[branch].longname : branches[branch].abbrevname);
if ( include_number && branches[branch].depth != 1 )
{
char buf[200];
if ( long_name )
{
// decapitalize 'the'
if ( result.find("The") == 0 )
result[0] = 't';
snprintf( buf, sizeof buf, "Level %d of %s",
lev, result.c_str() );
}
else if (lev)
snprintf( buf, sizeof buf, "%s:%d", result.c_str(), lev );
else
snprintf( buf, sizeof buf, "%s:$", result.c_str() );
result = buf;
}
return result;
}
// Takes a packed 'place' and returns a compact stringified place name.
// XXX: This is done in several other places; a unified function to
// describe places would be nice.
std::string short_place_name(unsigned short place)
{
return place_name( place, false, true );
}
// Prepositional form of branch level name. For example, "in the
// Abyss" or "on level 3 of the Main Dungeon".
std::string prep_branch_level_name(unsigned short packed_place)
{
std::string place = place_name( packed_place, true, true );
if (place.length() && place != "Pandemonium")
place[0] = tolower(place[0]);
return (place.find("level") == 0?
"on " + place
: "in " + place);
}
// Use current branch and depth
std::string prep_branch_level_name()
{
return prep_branch_level_name( get_packed_place() );
}
int absdungeon_depth(branch_type branch, int subdepth)
{
if (branch >= BRANCH_VESTIBULE_OF_HELL && branch <= BRANCH_THE_PIT)
return subdepth + 27 - (branch == BRANCH_VESTIBULE_OF_HELL);
else
{
--subdepth;
while ( branch != BRANCH_MAIN_DUNGEON )
{
subdepth += branches[branch].startdepth;
branch = branches[branch].parent_branch;
}
}
return subdepth;
}
int subdungeon_depth(branch_type branch, int depth)
{
return depth - absdungeon_depth(branch, 0);
}
int player_branch_depth()
{
return subdungeon_depth(you.where_are_you, you.your_level);
}
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: ability - acr - bang - beam - chardump - command - debug -
* decks - direct - effects - fight - files - food - it_use2 -
* it_use3 - item_use - items - macro - misc - monplace -
* monstuff - mstuff2 - mutation - ouch - overmap - player -
* religion - shopping - skills - spell - spl-book - spells -
* spells1 - spells2 - spells3 - spells4 - stuff - transfor -
* view
* *********************************************************************** */
void mpr(const char *inf, msg_channel_type channel = MSGCH_PLAIN, int param=0);
// 4.1-style mpr, currently named mprf for minimal disruption.
void mprf( msg_channel_type channel, int param, const char *format, ... );
void mprf( msg_channel_type channel, const char *format, ... );
void mprf( const char *format, ... );
#include "delay.h"
#include "stuff.h"
#include "travel.h"
#include "view.h"
#include "message.h"
#include "monstuff.h"
// [dshaligram] Maps can be mirrored; for every orientation, there must be
// a suitable mirror.
enum map_section_type // see maps.cc and dungeon.cc {dlb}
{
MAP_NONE = -1,
MAP_NORTH = 1, // 1
MAP_SOUTH,
MAP_EAST,
MAP_WEST,
MAP_NORTHWEST, // 5
MAP_NORTHEAST,
MAP_SOUTHWEST,
MAP_SOUTHEAST,
MAP_ENCOMPASS,
// A "floating" vault is placed somewhat like a minivault, away from
// the edges, although in other respects it behaves like a regular vault.
MAP_FLOAT,
MAP_NUM_SECTION_TYPES
};
enum armour_type
{
ARM_ROBE, // 0
ARM_LEATHER_ARMOUR,
ARM_RING_MAIL,
ARM_SCALE_MAIL,
ARM_CHAIN_MAIL,
ARM_SPLINT_MAIL, // 5
ARM_BANDED_MAIL,
ARM_PLATE_MAIL,
ARM_SHIELD,
ARM_CLOAK,
ARM_HELMET, // 10
ARM_GLOVES,
ARM_BOOTS,
ARM_BUCKLER,
ARM_LARGE_SHIELD,
ARM_DRAGON_HIDE, // 15
ARM_TROLL_HIDE,
ARM_CRYSTAL_PLATE_MAIL,
ARM_DRAGON_ARMOUR,
ARM_TROLL_LEATHER_ARMOUR,
ARM_ICE_DRAGON_HIDE, // 20
ARM_ICE_DRAGON_ARMOUR,
ARM_STEAM_DRAGON_HIDE,
ARM_STEAM_DRAGON_ARMOUR,
ARM_MOTTLED_DRAGON_HIDE,
ARM_MOTTLED_DRAGON_ARMOUR, // 25
ARM_STORM_DRAGON_HIDE,
ARM_STORM_DRAGON_ARMOUR,
ARM_GOLD_DRAGON_HIDE,
ARM_GOLD_DRAGON_ARMOUR,
ARM_ANIMAL_SKIN, // 30
ARM_SWAMP_DRAGON_HIDE,
ARM_SWAMP_DRAGON_ARMOUR,
ARM_STUDDED_LEATHER_ARMOUR,
ARM_CAP,
ARM_CENTAUR_BARDING, // 35
ARM_NAGA_BARDING,
NUM_ARMOURS
};
enum armour_property_type
{
PARM_AC, // 0
PARM_EVASION
};
enum boot_type // used in pluses2
{
TBOOT_BOOTS = 0,
TBOOT_NAGA_BARDING,
TBOOT_CENTAUR_BARDING,
NUM_BOOT_TYPES
};
enum brand_type // equivalent to (you.inv[].special or mitm[].special) % 30
{
SPWPN_NORMAL, // 0
SPWPN_FLAMING,
SPWPN_FREEZING,
SPWPN_HOLY_WRATH,
SPWPN_ELECTROCUTION,
SPWPN_ORC_SLAYING, // 5
SPWPN_VENOM,
SPWPN_PROTECTION,
SPWPN_DRAINING,
SPWPN_SPEED,
SPWPN_VORPAL, // 10
SPWPN_FLAME,
SPWPN_FROST,
SPWPN_VAMPIRICISM,
SPWPN_DISRUPTION,
SPWPN_PAIN, // 15
SPWPN_DISTORTION,
SPWPN_REACHING, // 17
SPWPN_RETURNING,
SPWPN_CONFUSE,
SPWPN_RANDART_I = 25, // 25
SPWPN_RANDART_II,
SPWPN_RANDART_III,
SPWPN_RANDART_IV,
SPWPN_RANDART_V,
NUM_SPECIAL_WEAPONS,
SPWPN_DUMMY_CRUSHING, // ONLY TEMPORARY USAGE -- converts to VORPAL
// everything above this point is a special artefact wield:
SPWPN_SINGING_SWORD = 181, // 181
SPWPN_WRATH_OF_TROG,
SPWPN_SCYTHE_OF_CURSES,
SPWPN_MACE_OF_VARIABILITY,
SPWPN_GLAIVE_OF_PRUNE, // 185
SPWPN_SCEPTRE_OF_TORMENT,
SPWPN_SWORD_OF_ZONGULDROK,
// these three are not generated randomly {dlb}
SPWPN_SWORD_OF_CEREBOV,
SPWPN_STAFF_OF_DISPATER,
SPWPN_SCEPTRE_OF_ASMODEUS, // 190
SPWPN_SWORD_OF_POWER,
SPWPN_KNIFE_OF_ACCURACY,
SPWPN_STAFF_OF_OLGREB,
SPWPN_VAMPIRES_TOOTH,
SPWPN_STAFF_OF_WUCAD_MU // 195
};
enum corpse_type
{
CORPSE_BODY, // 0
CORPSE_SKELETON
};
enum hands_reqd_type
{
HANDS_ONE,
HANDS_HALF,
HANDS_TWO,
HANDS_DOUBLE // not a level, marks double ended weapons (== half)
};
enum helmet_type
{
THELM_HELMET = 0x0000,
THELM_HELM = 0x0001,
THELM_CAP = 0x0002,
THELM_WIZARD_HAT = 0x0003,
THELM_NUM_TYPES = 4,
THELM_SPECIAL = 0x0004, // type used only for artefacts (mask, hat)
THELM_TYPE_MASK = 0x00ff,
THELM_DESC_PLAIN = 0x0000,
THELM_DESC_WINGED = 0x0100,
THELM_DESC_HORNED = 0x0200,
THELM_DESC_CRESTED = 0x0300,
THELM_DESC_PLUMED = 0x0400,
THELM_DESC_SPIKED = 0x0500,
THELM_DESC_VISORED = 0x0600,
THELM_DESC_JEWELLED = 0x0700,
THELM_DESC_MASK = 0xff00
};
enum jewellery_type
{
RING_FIRST_RING = 0,
RING_REGENERATION = RING_FIRST_RING, // 0
RING_PROTECTION,
RING_PROTECTION_FROM_FIRE,
RING_POISON_RESISTANCE,
RING_PROTECTION_FROM_COLD,
RING_STRENGTH, // 5
RING_SLAYING,
RING_SEE_INVISIBLE,
RING_INVISIBILITY,
RING_HUNGER,
RING_TELEPORTATION, // 10
RING_EVASION,
RING_SUSTAIN_ABILITIES,
RING_SUSTENANCE,
RING_DEXTERITY,
RING_INTELLIGENCE, // 15
RING_WIZARDRY,
RING_MAGICAL_POWER,
RING_LEVITATION,
RING_LIFE_PROTECTION,
RING_PROTECTION_FROM_MAGIC, // 20
RING_FIRE,
RING_ICE,
RING_TELEPORT_CONTROL, // 23
NUM_RINGS, // 24, keep as last ring; can overlap
// safely with first amulet.
AMU_FIRST_AMULET = 35,
AMU_RAGE = AMU_FIRST_AMULET, // 35
AMU_RESIST_SLOW,
AMU_CLARITY,
AMU_WARDING,
AMU_RESIST_CORROSION,
AMU_THE_GOURMAND, // 40
AMU_CONSERVATION,
AMU_CONTROLLED_FLIGHT,
AMU_INACCURACY,
AMU_RESIST_MUTATION,
NUM_JEWELLERY
};
enum launch_retval
{
LRET_FUMBLED = 0, // must be left as 0
LRET_LAUNCHED,
LRET_THROWN
};
enum misc_item_type
{
MISC_BOTTLED_EFREET, // 0
MISC_CRYSTAL_BALL_OF_SEEING,
MISC_AIR_ELEMENTAL_FAN,
MISC_LAMP_OF_FIRE,
MISC_STONE_OF_EARTH_ELEMENTALS,
MISC_LANTERN_OF_SHADOWS,
MISC_HORN_OF_GERYON,
MISC_BOX_OF_BEASTS,
MISC_CRYSTAL_BALL_OF_ENERGY,
MISC_EMPTY_EBONY_CASKET,
MISC_CRYSTAL_BALL_OF_FIXATION,
MISC_DISC_OF_STORMS,
// pure decks
MISC_DECK_OF_ESCAPE,
MISC_DECK_OF_DESTRUCTION,
MISC_DECK_OF_DUNGEONS,
MISC_DECK_OF_SUMMONING,
MISC_DECK_OF_WONDERS,
MISC_DECK_OF_PUNISHMENT,
// mixed decks
MISC_DECK_OF_WAR,
MISC_DECK_OF_CHANGES,
MISC_DECK_OF_DEFENSE,
MISC_RUNE_OF_ZOT,
NUM_MISCELLANY // mv: used for random generation
};
enum missile_type
{
MI_STONE, // 0
MI_ARROW,
MI_BOLT,
MI_DART,
MI_NEEDLE,
MI_LARGE_ROCK,
MI_SLING_BULLET,
MI_JAVELIN,
MI_THROWING_NET,
NUM_MISSILES,
MI_NONE // was MI_EGGPLANT... used for launch type detection
};
enum rune_type
{
// Note: that runes DIS-SWAMP have the same numeric value as the branch
RUNE_DIS = BRANCH_DIS,
RUNE_GEHENNA = BRANCH_GEHENNA,
RUNE_COCYTUS = BRANCH_COCYTUS,
RUNE_TARTARUS = BRANCH_TARTARUS,
RUNE_SLIME_PITS = BRANCH_SLIME_PITS,
RUNE_VAULTS = BRANCH_VAULTS,
RUNE_SNAKE_PIT = BRANCH_SNAKE_PIT,
RUNE_ELVEN_HALLS = BRANCH_ELVEN_HALLS, // unused
RUNE_TOMB = BRANCH_TOMB,
RUNE_SWAMP = BRANCH_SWAMP,
RUNE_SHOALS = BRANCH_SHOALS,
// Runes 50 and 51 are for Pandemonium (general demon) and the Abyss
RUNE_DEMONIC = 50,
RUNE_ABYSSAL,
// Runes 60-63 correspond to the Pandemonium demonlords,
// and are equal to the corresponding vault.
RUNE_MNOLEG = 60,
RUNE_LOM_LOBON,
RUNE_CEREBOV,
RUNE_GLOORX_VLOQ,
NUM_RUNE_TYPES, // should always be last
RUNE_NONE
};
enum scroll_type
{
SCR_IDENTIFY, // 0
SCR_TELEPORTATION,
SCR_FEAR,
SCR_NOISE,
SCR_REMOVE_CURSE,
SCR_DETECT_CURSE, // 5
SCR_SUMMONING,
SCR_ENCHANT_WEAPON_I,
SCR_ENCHANT_ARMOUR,
SCR_TORMENT,
SCR_RANDOM_USELESSNESS, // 10
SCR_CURSE_WEAPON,
SCR_CURSE_ARMOUR,
SCR_IMMOLATION,
SCR_BLINKING,
SCR_PAPER, // 15
SCR_MAGIC_MAPPING,
SCR_FORGETFULNESS,
SCR_ACQUIREMENT,
SCR_ENCHANT_WEAPON_II,
SCR_VORPALISE_WEAPON, // 20
SCR_RECHARGING,
SCR_ENCHANT_WEAPON_III,
NUM_SCROLLS
};
enum special_armour_type
{
SPARM_NORMAL, // 0
SPARM_RUNNING,
SPARM_FIRE_RESISTANCE,
SPARM_COLD_RESISTANCE,
SPARM_POISON_RESISTANCE,
SPARM_SEE_INVISIBLE, // 5
SPARM_DARKNESS,
SPARM_STRENGTH,
SPARM_DEXTERITY,
SPARM_INTELLIGENCE,
SPARM_PONDEROUSNESS, // 10
SPARM_LEVITATION,
SPARM_MAGIC_RESISTANCE,
SPARM_PROTECTION,
SPARM_STEALTH,
SPARM_RESISTANCE, // 15
SPARM_POSITIVE_ENERGY,
SPARM_ARCHMAGI,
SPARM_PRESERVATION, // 18
SPARM_RANDART_I = 25, // must remain at 25 for now - how high do they go? {dlb}
SPARM_RANDART_II = 26, // 26
SPARM_RANDART_III = 27, // 27
SPARM_RANDART_IV = 28, // 28
SPARM_RANDART_V = 29 // 29 - highest value found thus far {dlb}
};
enum special_missile_type // to separate from weapons in general {dlb}
{
SPMSL_NORMAL, // 0
SPMSL_FLAME, // 1
SPMSL_ICE, // 2
SPMSL_POISONED, // 3
SPMSL_POISONED_II, // 4 - unused
SPMSL_CURARE // 5
};
enum special_ring_type // jewellery mitm[].special values
{
SPRING_RANDART = 200,
SPRING_UNRANDART = 201
};
enum special_wield_type // you.special_wield
{
SPWLD_NONE, // 0
SPWLD_SING,
SPWLD_TROG,
SPWLD_CURSE,
SPWLD_VARIABLE, // 4
SPWLD_PRUNE, // 5 - implicit in it_use3::special_wielded() {dlb}
SPWLD_TORMENT, // 6
SPWLD_ZONGULDROK,
SPWLD_POWER,
SPWLD_WUCAD_MU, // 9
SPWLD_OLGREB, // 10
SPWLD_SHADOW = 50, // 50
SPWLD_NOISE // further differentiation useless -> removed (jpeg)
};
enum stave_type
{
// staves
STAFF_WIZARDRY = 0,
STAFF_POWER,
STAFF_FIRE,
STAFF_COLD,
STAFF_POISON,
STAFF_ENERGY,
STAFF_DEATH,
STAFF_CONJURATION,
STAFF_ENCHANTMENT,
STAFF_SUMMONING,
STAFF_AIR,
STAFF_EARTH,
STAFF_CHANNELING,
// rods
STAFF_SMITING, // must be first rod!
STAFF_SPELL_SUMMONING,
STAFF_DESTRUCTION_I,
STAFF_DESTRUCTION_II,
STAFF_DESTRUCTION_III,
STAFF_DESTRUCTION_IV,
STAFF_WARDING,
STAFF_DISCOVERY,
STAFF_DEMONOLOGY,
STAFF_STRIKING,
STAFF_VENOM,
NUM_STAVES // must remain last member {dlb}
};
enum weapon_type
{
// Base weapons
WPN_CLUB, // 0
WPN_MACE,
WPN_FLAIL,
WPN_DAGGER,
WPN_MORNINGSTAR,
WPN_SHORT_SWORD, // 5
WPN_LONG_SWORD,
WPN_GREAT_SWORD,
WPN_SCIMITAR,
WPN_HAND_AXE,
WPN_BATTLEAXE, // 10
WPN_SPEAR,
WPN_HALBERD,
WPN_SLING,
WPN_BOW,
WPN_CROSSBOW, // 15
WPN_HAND_CROSSBOW,
WPN_GLAIVE,
WPN_QUARTERSTAFF,
// these three not created ordinarily
WPN_SCYTHE,
WPN_GIANT_CLUB, // 20
WPN_GIANT_SPIKED_CLUB,
// "rare" weapons - some have special cases and are uncommon
WPN_EVENINGSTAR,
WPN_QUICK_BLADE,
WPN_KATANA,
WPN_EXECUTIONERS_AXE, // 25
WPN_DOUBLE_SWORD,
WPN_TRIPLE_SWORD,
WPN_HAMMER,
WPN_ANCUS,
WPN_WHIP, // 30
WPN_SABRE,
WPN_DEMON_BLADE,
WPN_DEMON_WHIP,
WPN_DEMON_TRIDENT,
WPN_BROAD_AXE, // 35
// base items (continued)
WPN_WAR_AXE,
WPN_TRIDENT,
WPN_SPIKED_FLAIL,
WPN_GREAT_MACE,
WPN_DIRE_FLAIL, // 40
WPN_KNIFE,
WPN_BLOWGUN,
WPN_FALCHION,
WPN_BLESSED_BLADE, // 44
WPN_LONGBOW,
WPN_LAJATANG,
WPN_LOCHABER_AXE,
NUM_WEAPONS, // 48 - must be last regular member {dlb}
// special cases
WPN_UNARMED = 500, // 500
WPN_UNKNOWN = 1000, // 1000
WPN_RANDOM
};
enum weapon_description_type
{
DWPN_PLAIN = 0, // 0 - added to round out enum {dlb}
DWPN_RUNED = 1, // 1
DWPN_GLOWING,
DWPN_ORCISH,
DWPN_ELVEN,
DWPN_DWARVEN // 5
};
enum weapon_property_type
{
PWPN_DAMAGE, // 0
PWPN_HIT,
PWPN_SPEED,
PWPN_ACQ_WEIGHT
};
enum vorpal_damage_type
{
// Types of damage a weapon can do... currently assuming that anything
// with BLUDGEON always does "AND" with any other specified types,
// and and sets not including BLUDGEON are "OR".
DAM_BASH = 0x0000, // non-melee weapon blugeoning
DAM_BLUDGEON = 0x0001, // crushing
DAM_SLICE = 0x0002, // slicing/chopping
DAM_PIERCE = 0x0004, // stabbing/piercing
DAM_WHIP = 0x0008, // whip slashing (no butcher)
// These are used for vorpal weapon desc (don't set more than one)
DVORP_NONE = 0x0000, // used for non-melee weapons
DVORP_CRUSHING = 0x1000,
DVORP_SLICING = 0x2000,
DVORP_PIERCING = 0x3000,
DVORP_CHOPPING = 0x4000, // used for axes
DVORP_SLASHING = 0x5000, // used for whips
DVORP_STABBING = 0x6000, // used for knives/daggers
DVORP_CLAWING = 0x7000, // claw damage
// These are shortcuts to tie vorpal/damage types for easy setting...
// as above, setting more than one vorpal type is trouble.
DAMV_NON_MELEE = DVORP_NONE | DAM_BASH, // launchers
DAMV_CRUSHING = DVORP_CRUSHING | DAM_BLUDGEON,
DAMV_SLICING = DVORP_SLICING | DAM_SLICE,
DAMV_PIERCING = DVORP_PIERCING | DAM_PIERCE,
DAMV_CHOPPING = DVORP_CHOPPING | DAM_SLICE,
DAMV_SLASHING = DVORP_SLASHING | DAM_WHIP,
DAMV_STABBING = DVORP_STABBING | DAM_PIERCE,
DAM_MASK = 0x0fff, // strips vorpal specification
DAMV_MASK = 0xf000 // strips non-vorpal specification
};
// NOTE: This order is very special! Its basically the same as ZAP_*,
// and there are bits of the code that still use that fact.. see zap_wand().
enum wand_type // mitm[].subtype
{
WAND_FLAME, // 0
WAND_FROST,
WAND_SLOWING,
WAND_HASTING,
WAND_MAGIC_DARTS,
WAND_HEALING, // 5
WAND_PARALYSIS,
WAND_FIRE,
WAND_COLD,
WAND_CONFUSION,
WAND_INVISIBILITY, // 10
WAND_DIGGING,
WAND_FIREBALL,
WAND_TELEPORTATION,
WAND_LIGHTNING,
WAND_POLYMORPH_OTHER, // 15
WAND_ENSLAVEMENT,
WAND_DRAINING,
WAND_RANDOM_EFFECTS,
WAND_DISINTEGRATION,
NUM_WANDS // must remain last member {dlb}
};
enum zap_count_type
{
ZAPCOUNT_EMPTY = -1,
ZAPCOUNT_UNKNOWN = -2
};
}
bool is_deck(const item_def &item)
{
return item.base_type == OBJ_MISCELLANY
&& (item.sub_type >= MISC_DECK_OF_ESCAPE &&
item.sub_type <= MISC_DECK_OF_DEFENSE);
}
deck_rarity_type deck_rarity(const item_def &item)
{
ASSERT( is_deck(item) );
switch (item.colour)
{
case BLACK: case BLUE: case GREEN: case CYAN: case RED:
default:
return DECK_RARITY_COMMON;
case MAGENTA: case BROWN:
return DECK_RARITY_RARE;
case LIGHTMAGENTA:
return DECK_RARITY_LEGENDARY;
}
enum item_type_id_type
{
IDTYPE_WANDS = 0,
IDTYPE_SCROLLS,
IDTYPE_JEWELLERY,
IDTYPE_POTIONS,
NUM_IDTYPE
};
enum item_type_id_state_type // used for values in id[4][50]
{
ID_UNKNOWN_TYPE = 0,
ID_MON_TRIED_TYPE,
ID_TRIED_TYPE,
ID_KNOWN_TYPE
};
// [dshaligram] If you edit potion colours/descriptions, also update
// itemname.cc.
enum potion_description_colour_type
{
PDC_CLEAR,
PDC_BLUE,
PDC_BLACK,
PDC_SILVERY,
PDC_CYAN,
PDC_PURPLE,
PDC_ORANGE,
PDC_INKY,
PDC_RED,
PDC_YELLOW,
PDC_GREEN,
PDC_BROWN,
PDC_PINK,
PDC_WHITE,
PDC_NCOLOURS
};
// [dshaligram] If you edit potion colours/descriptions, also update
// itemname.cc.
enum potion_description_qualifier_type
{
PDQ_NONE,
PDQ_BUBBLING,
PDQ_FUMING,
PDQ_FIZZY,
PDQ_VISCOUS,
PDQ_LUMPY,
PDQ_SMOKY,
PDQ_GLOWING,
PDQ_SEDIMENTED,
PDQ_METALLIC,
PDQ_MURKY,
PDQ_GLUGGY,
PDQ_OILY,
PDQ_SLIMY,
PDQ_EMULSIFIED,
PDQ_NQUALS
};
enum potion_type
{
POT_HEALING, // 0
POT_HEAL_WOUNDS,
POT_SPEED,
POT_MIGHT,
POT_GAIN_STRENGTH,
POT_GAIN_DEXTERITY, // 5
POT_GAIN_INTELLIGENCE,
POT_LEVITATION,
POT_POISON,
POT_SLOWING,
POT_PARALYSIS, // 10
POT_CONFUSION,
POT_INVISIBILITY,
POT_PORRIDGE,
POT_DEGENERATION,
POT_DECAY, // 15
POT_WATER,
POT_EXPERIENCE,
POT_MAGIC,
POT_RESTORE_ABILITIES,
POT_STRONG_POISON, // 20
POT_BERSERK_RAGE,
POT_CURE_MUTATION,
POT_MUTATION,
POT_BLOOD,
POT_RESISTANCE,
NUM_POTIONS
};
struct system_environment
{
std::string crawl_name;
std::string crawl_pizza;
std::string crawl_rc;
std::string crawl_dir;
std::string morgue_dir;
std::string crawl_base; // Directory from argv[0], may be used to
// locate datafiles.
std::string home; // only used by MULTIUSER systems
bool board_with_nail; // Easter Egg silliness
#ifdef DGL_SIMPLE_MESSAGING
std::string messagefile; // File containing messages from other users.
bool have_messages; // There are messages waiting to be read.
unsigned message_check_tick;
#endif
std::string scorefile;
std::vector<std::string> cmd_args;
int map_gen_iters;
};
extern system_environment SysEnv;
enum food_type
{
FOOD_MEAT_RATION, // 0
FOOD_BREAD_RATION,
FOOD_PEAR,
FOOD_APPLE,
FOOD_CHOKO,
FOOD_HONEYCOMB, // 5
FOOD_ROYAL_JELLY,
FOOD_SNOZZCUMBER,
FOOD_PIZZA,
FOOD_APRICOT,
FOOD_ORANGE, // 10
FOOD_BANANA,
FOOD_STRAWBERRY,
FOOD_RAMBUTAN,
FOOD_LEMON,
FOOD_GRAPE, // 15
FOOD_SULTANA,
FOOD_LYCHEE,
FOOD_BEEF_JERKY,
FOOD_CHEESE,
FOOD_SAUSAGE, // 20
FOOD_CHUNK,
NUM_FOODS
};
struct monsters;
struct ait_hp_loss;
struct activity_interrupt_data
{
activity_interrupt_payload_type apt;
const void *data;
std::string context;
activity_interrupt_data()
: apt(AIP_NONE), data(NULL), context()
{
}
activity_interrupt_data(const int *i)
: apt(AIP_INT), data(i), context()
{
}
activity_interrupt_data(const char *s)
: apt(AIP_STRING), data(s), context()
{
}
activity_interrupt_data(const std::string &s)
: apt(AIP_STRING), data(s.c_str()), context()
{
}
activity_interrupt_data(const monsters *m, const std::string &ctx = "")
: apt(AIP_MONSTER), data(m), context(ctx)
{
}
activity_interrupt_data(const ait_hp_loss *ahl)
: apt(AIP_HP_LOSS), data(ahl), context()
{
}
activity_interrupt_data(const activity_interrupt_data &a)
: apt(a.apt), data(a.data), context(a.context)
{
}
};
};
struct ray_def
{
public:
double accx;
double accy;
double slope;
// Quadrant 1: down-right
// Quadrant 2: down-left
// Quadrant 3: up-left
// Quadrant 4: up-right
int quadrant;
int fullray_idx; // for cycling: where did we come from?
public:
ray_def();
int x() const { return static_cast<int>(accx); }
int y() const { return static_cast<int>(accy); }
coord_def pos() const { return coord_def(x(), y()); }
// returns the direction taken (0,1,2)
int advance(bool shorten = false, const coord_def *p = NULL);
int advance_through(const coord_def &point);
void advance_and_bounce();
void regress();
private:
int raw_advance();
double reflect(bool x, double oldc, double newc) const;
double reflect(double x, double c) const;
void set_reflect_point(const double oldx, const double oldy,
double *newx, double *newy,
bool blocked_x, bool blocked_y);
};
// output from direction() function:
struct dist
{
bool isValid; // valid target chosen?
bool isTarget; // target (true), or direction (false)?
bool isMe; // selected self (convenience: tx == you.x_pos,
// ty == you.y_pos)
bool isEndpoint; // Does the player want the attack to stop at (tx,ty)?
bool isCancel; // user cancelled (usually <ESC> key)
bool choseRay; // user wants a specific beam
int tx,ty; // target x,y or logical extension of beam to map edge
int dx,dy; // delta x and y if direction - always -1,0,1
ray_def ray; // ray chosen if necessary
// internal use - ignore
int prev_target; // previous target
// target - source (source == you.pos())
coord_def target() const
{
return coord_def(tx, ty);
}
struct bolt
{
// INPUT parameters set by caller
int range; // minimum range
int rangeMax; // maximum range
int type; // missile gfx
int colour;
int flavour;
int source_x, source_y; // beam origin
dice_def damage;
int ench_power, hit;
int target_x, target_y; // intended target
char thrower; // what kind of thing threw this?
char ex_size; // explosion radius (0==none)
int beam_source; // NON_MONSTER or monster index #
std::string name;
bool is_beam; // beams? (can hits multiple targets?)
bool is_explosion;
bool is_big_cloud; // expands into big_cloud at endpoint
bool is_enchant; // no block/dodge, but mag resist
bool is_energy; // mostly energy/non-physical attack
bool is_launched; // was fired from launcher?
bool is_thrown; // was thrown from hand?
bool target_first; // targeting by direction
bool aimed_at_spot; // aimed at (x,y), should not cross
std::string aux_source; // source of KILL_MISC beams
// OUTPUT parameters (tracing, ID)
bool obvious_effect; // did an 'obvious' effect happen?
bool effect_known; // did we _know_ this would happen?
int fr_count, foe_count; // # of times a friend/foe is "hit"
int fr_power, foe_power; // total levels/hit dice affected
// INTERNAL use - should not usually be set outside of beam.cc
bool is_tracer; // is this a tracer?
bool aimed_at_feet; // this was aimed at self!
bool msg_generated; // an appropriate msg was already mpr'd
bool in_explosion_phase; // explosion phase (as opposed to beam phase)
bool smart_monster; // tracer firer can guess at other mons. resists?
bool can_see_invis; // tracer firer can see invisible?
mon_attitude_type attitude; // attitude of whoever fired tracer
int foe_ratio; // 100* foe ratio (see mons_should_fire())
bool chose_ray; // do we want a specific ray?
ray_def ray; // shoot on this specific ray
public:
// A constructor to try and fix some of the bugs that occur because
// this struct never seems to be properly initialized. Definition
// is over in beam.cc.
bolt();
void set_target(const dist &);
// Returns YOU_KILL or MON_KILL, depending on the source of the beam.
killer_type killer() const;
coord_def target() const
{
return (coord_def(target_x, target_y));
}
};
};
class input_history
{
public:
input_history(size_t size);
void new_input(const std::string &s);
void clear();
const std::string *prev();
const std::string *next();
void go_end();
private:
typedef std::list<std::string> string_list;
string_list history;
string_list::iterator pos;
size_t maxsize;
KillMaster kills;
// NOTE: The kills member is a pointer to a KillMaster object,
// rather than the object itself, so that we can get away with
// just a foward declare of the KillMaster class, rather than
// having to #include Kills.h and thus make every single .cc file
// dependant on Kills.h. Having a pointer means that we have
// to do our own implementations of copying the player object,
// since the default implementations will lead to the kills member
// pointing to freed memory, or worse yet lead to the same piece of
// memory being freed twice.
KillMaster* kills;
struct mon_attack_def
{
mon_attack_type type;
mon_attack_flavour flavour;
int damage;
static mon_attack_def attk(int damage,
mon_attack_type type = AT_HIT,
mon_attack_flavour flav = AF_PLAIN)
{
mon_attack_def def = { type, flav, damage };
return (def);
}
};
// Track various aspects of Crawl game state.
struct game_state
{
bool mouse_enabled; // True if mouse input is currently relevant.
bool waiting_for_command; // True when the game is waiting for a command.
bool terminal_resized; // True if the term was resized and we need to
// take action to handle it.
bool io_inited; // Is curses or the equivalent initialised?
bool need_save; // Set to true when game has started.
bool saving_game; // Set to true while in save_game.
bool updating_scores; // Set to true while updating hiscores.
int seen_hups; // Set to true if SIGHUP received.
bool map_stat_gen; // Set if we're generating stats on maps.
bool unicode_ok; // Is unicode support available?
std::string (*glyph2strfn)(unsigned glyph);
int (*multibyte_strlen)(const std::string &s);
void (*terminal_resize_handler)();
void (*terminal_resize_check)();
game_state() : mouse_enabled(false), waiting_for_command(false),
terminal_resized(false), io_inited(false), need_save(false),
saving_game(false), updating_scores(false),
seen_hups(0), map_stat_gen(false), unicode_ok(false),
glyph2strfn(NULL), multibyte_strlen(NULL),
terminal_resize_handler(NULL), terminal_resize_check(NULL)
{
}
void check_term_size() const
{
if (terminal_resize_check)
(*terminal_resize_check)();
}
};
extern game_state crawl_state;
struct system_environment
{
std::string crawl_name;
std::string crawl_pizza;
std::string crawl_rc;
std::string crawl_dir;
std::string morgue_dir;
std::string crawl_base; // Directory from argv[0], may be used to
// locate datafiles.
std::string home; // only used by MULTIUSER systems
bool board_with_nail; // Easter Egg silliness
#ifdef DGL_SIMPLE_MESSAGING
std::string messagefile; // File containing messages from other users.
bool have_messages; // There are messages waiting to be read.
unsigned message_check_tick;
#endif
std::string scorefile;
std::vector<std::string> cmd_args;
int map_gen_iters;
};
extern system_environment SysEnv;
struct crawl_view_geometry
{
public:
coord_def termsz; // Size of the terminal.
coord_def viewp; // Left-top pos of viewport.
coord_def viewsz; // Size of the viewport (play area).
coord_def hudp; // Left-top pos of status area.
coord_def hudsz; // Size of the status area.
coord_def msgp; // Left-top pos of the message pane.
coord_def msgsz; // Size of the message pane.
coord_def vgrdc; // What grid pos is at the centre of the view
// usually you.pos().
coord_def viewhalfsz;
coord_def glos1, glos2; // LOS limit grid coords (inclusive)
coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive)
coord_def mousep; // Where the mouse is.
static const int message_min_lines = 7;
static const int hud_min_width = 41;
static const int hud_min_gutter = 3;
static const int hud_max_gutter = 6;
private:
coord_def last_player_pos;
public:
crawl_view_geometry();
void init_geometry();
void init_view();
void set_player_at(const coord_def &c, bool force_centre = false);
coord_def view_centre() const
{
return viewp + viewhalfsz;
}
bool in_grid_los(const coord_def &c) const
{
return (c.x >= glos1.x && c.x <= glos2.x
&& c.y >= glos1.y && c.y <= glos2.y);
}
bool in_view_los(const coord_def &c) const
{
return (c.x >= vlos1.x && c.x <= vlos2.x
&& c.y >= vlos1.y && c.y <= vlos2.y);
}
bool in_view_viewport(const coord_def &c) const
{
return (c.x >= viewp.x && c.y >= viewp.y
&& c.x < viewp.x + viewsz.x
&& c.y < viewp.y + viewsz.y);
}
bool in_grid_viewport(const coord_def &c) const
{
return in_view_viewport(c - vgrdc + view_centre());
}
};
extern crawl_view_geometry crawl_view;
struct tagHeader
{
short tagID;
long offset;
};
extern const struct coord_def Compass[8];
extern const char* god_gain_power_messages[MAX_NUM_GODS][MAX_GOD_ABILITIES];
typedef int keycode_type;
typedef FixedArray < item_type_id_state_type, 4, 50 > id_arr;
enum ability_flag_type
{
ABFLAG_NONE = 0x00000000,
ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
ABFLAG_DELAY = 0x00000002, // ability has its own delay (ie glamour)
ABFLAG_PAIN = 0x00000004, // ability must hurt player (ie torment)
ABFLAG_EXHAUSTION = 0x00000008, // fails if you.exhausted
ABFLAG_INSTANT = 0x00000010, // doesn't take time to use
ABFLAG_PERMANENT_HP = 0x00000020, // costs permanent HPs
ABFLAG_PERMANENT_MP = 0x00000040, // costs permanent MPs
ABFLAG_CONF_OK = 0x00000080 // can use even if confused.
};
enum activity_interrupt_payload_type
{
AIP_NONE,
AIP_INT,
AIP_STRING,
AIP_MONSTER,
AIP_HP_LOSS
};
};
// Various ways to get the acquirement effect.
enum acquirement_agent_type
{
AQ_SCROLL = 0,
// Empty space for the gods
AQ_CARD_GENIE = 100,
AQ_WIZMODE = 200
};
enum armour_type
{
ARM_ROBE, // 0
ARM_LEATHER_ARMOUR,
ARM_RING_MAIL,
ARM_SCALE_MAIL,
ARM_CHAIN_MAIL,
ARM_SPLINT_MAIL, // 5
ARM_BANDED_MAIL,
ARM_PLATE_MAIL,
ARM_SHIELD,
ARM_CLOAK,
ARM_HELMET, // 10
ARM_GLOVES,
ARM_BOOTS,
ARM_BUCKLER,
ARM_LARGE_SHIELD,
ARM_DRAGON_HIDE, // 15
ARM_TROLL_HIDE,
ARM_CRYSTAL_PLATE_MAIL,
ARM_DRAGON_ARMOUR,
ARM_TROLL_LEATHER_ARMOUR,
ARM_ICE_DRAGON_HIDE, // 20
ARM_ICE_DRAGON_ARMOUR,
ARM_STEAM_DRAGON_HIDE,
ARM_STEAM_DRAGON_ARMOUR,
ARM_MOTTLED_DRAGON_HIDE,
ARM_MOTTLED_DRAGON_ARMOUR, // 25
ARM_STORM_DRAGON_HIDE,
ARM_STORM_DRAGON_ARMOUR,
ARM_GOLD_DRAGON_HIDE,
ARM_GOLD_DRAGON_ARMOUR,
ARM_ANIMAL_SKIN, // 30
ARM_SWAMP_DRAGON_HIDE,
ARM_SWAMP_DRAGON_ARMOUR,
ARM_STUDDED_LEATHER_ARMOUR,
ARM_CAP,
ARM_CENTAUR_BARDING, // 35
ARM_NAGA_BARDING,
NUM_ARMOURS
enum band_type
{
BAND_NO_BAND = 0,
BAND_KOBOLDS = 1,
BAND_ORCS,
BAND_ORC_KNIGHT,
BAND_KILLER_BEES,
BAND_FLYING_SKULLS, // 5
BAND_SLIME_CREATURES,
BAND_YAKS,
BAND_UGLY_THINGS,
BAND_HELL_HOUNDS,
BAND_JACKALS, // 10
BAND_HELL_KNIGHTS,
BAND_ORC_HIGH_PRIEST,
BAND_GNOLLS, // 13
BAND_BUMBLEBEES = 16,
BAND_CENTAURS,
BAND_YAKTAURS,
BAND_INSUBSTANTIAL_WISPS,
BAND_OGRE_MAGE, // 20
BAND_DEATH_YAKS,
BAND_NECROMANCER,
BAND_BALRUG,
BAND_CACODEMON,
BAND_EXECUTIONER, // 25
BAND_HELLWING,
BAND_DEEP_ELF_FIGHTER,
BAND_DEEP_ELF_KNIGHT,
BAND_DEEP_ELF_HIGH_PRIEST,
BAND_KOBOLD_DEMONOLOGIST, // 30
BAND_NAGAS,
BAND_WAR_DOGS,
BAND_GREY_RATS,
BAND_GREEN_RATS,
BAND_ORANGE_RATS, // 35
BAND_SHEEP,
BAND_GHOULS,
BAND_DEEP_TROLLS,
BAND_HOGS,
BAND_HELL_HOGS, // 40
BAND_GIANT_MOSQUITOES,
BAND_BOGGARTS,
BAND_BLINK_FROGS,
BAND_SKELETAL_WARRIORS, // 44
BAND_DRACONIAN, // 45
BAND_PANDEMONIUM_DEMON,
NUM_BANDS // always last
};
CE_NOCORPSE, // 0
CE_CLEAN, // 1
CE_CONTAMINATED, // 2
CE_POISONOUS, // 3
CE_HCL, // 4
CE_MUTAGEN_RANDOM, // 5
CE_MUTAGEN_GOOD, // 6 - may be worth implementing {dlb}
CE_MUTAGEN_BAD, // 7 - may be worth implementing {dlb}
CE_RANDOM, // 8 - not used, but may be worth implementing {dlb}
CE_ROTTEN = 50 // 50 - must remain at 50 for now {dlb}
CONFIRM_NONE_EASY,
CONFIRM_SAFE_EASY,
CONFIRM_ALL_EASY
enum deck_rarity_type
{
DECK_RARITY_COMMON,
DECK_RARITY_RARE,
DECK_RARITY_LEGENDARY
};
enum deck_type
{
// pure decks
DECK_OF_ESCAPE,
DECK_OF_DESTRUCTION,
DECK_OF_DUNGEONS,
DECK_OF_SUMMONING,
DECK_OF_WONDERS
};
};
enum demon_beam_type
{
DMNBM_HELLFIRE, // 0
DMNBM_SMITING,
DMNBM_BRAIN_FEED,
DMNBM_MUTATION
};
enum demon_class_type
{
DEMON_LESSER, // 0: Class V
DEMON_COMMON, // 1: Class II-IV
DEMON_GREATER, // 2: Class I
DEMON_RANDOM // any of the above
};
// various elemental colour schemes... used for abstracting random short lists
// MUST match the order in initfile.cc or breakage results.
enum element_type
{
EC_FIRE = 32, // fiery colours (must be first and > highest colour)
EC_ICE, // icy colours
EC_EARTH, // earthy colours
EC_ELECTRICITY, // electrical side of air
EC_AIR, // non-electric and general air magic
EC_POISON, // used only for venom mage and stalker stuff
EC_WATER, // used only for the elemental
EC_MAGIC, // general magical effect
EC_MUTAGENIC, // transmute, poly, radiation effects
EC_WARP, // teleportation and anything similar
EC_ENCHANT, // magical enhancements
EC_HEAL, // holy healing (not necromantic stuff)
EC_HOLY, // general "good" god effects
EC_DARK, // darkness
EC_DEATH, // currently only assassin (and equal to EC_NECRO)
EC_NECRO, // necromancy stuff
EC_UNHOLY, // demonology stuff
EC_VEHUMET, // vehumet's odd-ball colours
EC_BEOGH, // Beogh altar colours
EC_CRYSTAL, // colours of crystal
EC_BLOOD, // colours of blood
EC_SMOKE, // colours of smoke
EC_SLIME, // colours of slime
EC_JEWEL, // colourful
EC_ELVEN, // used for colouring elf fabric items
EC_DWARVEN, // used for colouring dwarf fabric items
EC_ORCISH, // used for colouring orc fabric items
EC_GILA, // gila monster colours
EC_FLOOR, // colour of the area's floor
EC_ROCK, // colour of the area's rock
EC_STONE, // colour of the area's stone
EC_MIST, // colour of mist
EC_SHIMMER_BLUE, // shimmering colours of blue.
EC_RANDOM // any colour (except BLACK)
enum fire_type
{
FIRE_NONE = 0x0000,
FIRE_LAUNCHER = 0x0001,
FIRE_DART = 0x0002,
FIRE_STONE = 0x0004,
FIRE_DAGGER = 0x0008,
FIRE_JAVELIN = 0x0010,
FIRE_SPEAR = 0x0020,
FIRE_HAND_AXE = 0x0040,
FIRE_CLUB = 0x0080,
FIRE_ROCK = 0x0100,
FIRE_NET = 0x0200
};
};
enum food_type
{
FOOD_MEAT_RATION, // 0
FOOD_BREAD_RATION,
FOOD_PEAR,
FOOD_APPLE,
FOOD_CHOKO,
FOOD_HONEYCOMB, // 5
FOOD_ROYAL_JELLY,
FOOD_SNOZZCUMBER,
FOOD_PIZZA,
FOOD_APRICOT,
FOOD_ORANGE, // 10
FOOD_BANANA,
FOOD_STRAWBERRY,
FOOD_RAMBUTAN,
FOOD_LEMON,
FOOD_GRAPE, // 15
FOOD_SULTANA,
FOOD_LYCHEE,
FOOD_BEEF_JERKY,
FOOD_CHEESE,
FOOD_SAUSAGE, // 20
FOOD_CHUNK,
NUM_FOODS
};
enum genus_type
{
GENPC_DRACONIAN, // 0
GENPC_ELVEN, // 1
GENPC_DWARVEN, // 2
GENPC_OGRE
};
enum hands_reqd_type
{
HANDS_ONE,
HANDS_HALF,
HANDS_TWO,
HANDS_DOUBLE // not a level, marks double ended weapons (== half)
};
enum helmet_type
{
THELM_HELMET = 0x0000,
THELM_HELM = 0x0001,
THELM_CAP = 0x0002,
THELM_WIZARD_HAT = 0x0003,
THELM_NUM_TYPES = 4,
THELM_SPECIAL = 0x0004, // type used only for artefacts (mask, hat)
THELM_TYPE_MASK = 0x00ff,
THELM_DESC_PLAIN = 0x0000,
THELM_DESC_WINGED = 0x0100,
THELM_DESC_HORNED = 0x0200,
THELM_DESC_CRESTED = 0x0300,
THELM_DESC_PLUMED = 0x0400,
THELM_DESC_SPIKED = 0x0500,
THELM_DESC_VISORED = 0x0600,
THELM_DESC_JEWELLED = 0x0700,
THELM_DESC_MASK = 0xff00
};
enum boot_type // used in pluses2
{
TBOOT_BOOTS = 0,
TBOOT_NAGA_BARDING,
TBOOT_CENTAUR_BARDING,
NUM_BOOT_TYPES
};
enum item_description_type
{
IDESC_WANDS = 0,
IDESC_POTIONS,
IDESC_SCROLLS, // special field (like the others)
IDESC_RINGS,
IDESC_SCROLLS_II,
NUM_IDESC
};
enum item_make_species_type
{
MAKE_ITEM_ELVEN = 1,
MAKE_ITEM_DWARVEN = 2,
MAKE_ITEM_ORCISH = 3,
MAKE_ITEM_NO_RACE = 100,
MAKE_ITEM_RANDOM_RACE = 250
};
enum item_origin_dump_selector
{
IODS_PRICE = 0, // Extra info is provided based on price
IODS_ARTEFACTS = 1, // Extra information on artefacts
IODS_EGO_ARMOUR = 2,
IODS_EGO_WEAPON = 4,
IODS_JEWELLERY = 8,
IODS_RUNES = 16,
IODS_RODS = 32,
IODS_STAVES = 64,
IODS_BOOKS = 128,
IODS_EVERYTHING = 0xFF
};
enum item_type_id_type
{
IDTYPE_WANDS = 0,
IDTYPE_SCROLLS,
IDTYPE_JEWELLERY,
IDTYPE_POTIONS,
NUM_IDTYPE
};
enum item_type_id_state_type // used for values in id[4][50]
{
ID_UNKNOWN_TYPE = 0,
ID_MON_TRIED_TYPE,
ID_TRIED_TYPE,
ID_KNOWN_TYPE
};
enum jewellery_type
{
RING_FIRST_RING = 0,
RING_REGENERATION = RING_FIRST_RING, // 0
RING_PROTECTION,
RING_PROTECTION_FROM_FIRE,
RING_POISON_RESISTANCE,
RING_PROTECTION_FROM_COLD,
RING_STRENGTH, // 5
RING_SLAYING,
RING_SEE_INVISIBLE,
RING_INVISIBILITY,
RING_HUNGER,
RING_TELEPORTATION, // 10
RING_EVASION,
RING_SUSTAIN_ABILITIES,
RING_SUSTENANCE,
RING_DEXTERITY,
RING_INTELLIGENCE, // 15
RING_WIZARDRY,
RING_MAGICAL_POWER,
RING_LEVITATION,
RING_LIFE_PROTECTION,
RING_PROTECTION_FROM_MAGIC, // 20
RING_FIRE,
RING_ICE,
RING_TELEPORT_CONTROL, // 23
NUM_RINGS, // 24, keep as last ring; can overlap
// safely with first amulet.
AMU_FIRST_AMULET = 35,
AMU_RAGE = AMU_FIRST_AMULET, // 35
AMU_RESIST_SLOW,
AMU_CLARITY,
AMU_WARDING,
AMU_RESIST_CORROSION,
AMU_THE_GOURMAND, // 40
AMU_CONSERVATION,
AMU_CONTROLLED_FLIGHT,
AMU_INACCURACY,
AMU_RESIST_MUTATION,
NUM_JEWELLERY
};
enum kill_method_type
{
KILLED_BY_MONSTER, // 0
KILLED_BY_POISON,
KILLED_BY_CLOUD,
KILLED_BY_BEAM, // 3
KILLED_BY_DEATHS_DOOR, // should be deprecated, but you never know {dlb}
KILLED_BY_LAVA, // 5
KILLED_BY_WATER,
KILLED_BY_STUPIDITY,
KILLED_BY_WEAKNESS,
KILLED_BY_CLUMSINESS,
KILLED_BY_TRAP, // 10
KILLED_BY_LEAVING,
KILLED_BY_WINNING,
KILLED_BY_QUITTING,
KILLED_BY_DRAINING,
KILLED_BY_STARVATION, // 15
KILLED_BY_FREEZING,
KILLED_BY_BURNING,
KILLED_BY_WILD_MAGIC,
KILLED_BY_XOM,
KILLED_BY_STATUE, // 20
KILLED_BY_ROTTING,
KILLED_BY_TARGETTING,
KILLED_BY_SPORE,
KILLED_BY_TSO_SMITING,
KILLED_BY_PETRIFICATION, // 25
KILLED_BY_SOMETHING = 27,
KILLED_BY_FALLING_DOWN_STAIRS,
KILLED_BY_ACID,
KILLED_BY_CURARE,
KILLED_BY_MELTING,
KILLED_BY_BLEEDING,
KILLED_BY_BEOGH_SMITING,
NUM_KILLBY
#define YOU_KILL(x) ((x) == KILL_YOU || (x) == KILL_YOU_MISSILE \
|| (x) == KILL_YOU_CONF)
#define MON_KILL(x) ((x) == KILL_MON || (x) == KILL_MON_MISSILE)
enum launch_retval
{
LRET_FUMBLED = 0, // must be left as 0
LRET_LAUNCHED,
LRET_THROWN
};
};
// [dshaligram] Maps can be mirrored; for every orientation, there must be
// a suitable mirror.
enum map_section_type // see maps.cc and dungeon.cc {dlb}
{
MAP_NONE = -1,
MAP_NORTH = 1, // 1
MAP_SOUTH,
MAP_EAST,
MAP_WEST,
MAP_NORTHWEST, // 5
MAP_NORTHEAST,
MAP_SOUTHWEST,
MAP_SOUTHEAST,
MAP_ENCOMPASS,
// A "floating" vault is placed somewhat like a minivault, away from
// the edges, although in other respects it behaves like a regular vault.
MAP_FLOAT,
MAP_NUM_SECTION_TYPES
// if you mess with this list, you'll need to make changes in initfile.cc
// to message_channel_names, and probably also to message.cc to colour
// everything properly
enum msg_channel_type
enum mon_holy_type // matches (char) H_foo in mon-util.h, see: monster_holiness()
MSGCH_PLAIN, // regular text
MSGCH_PROMPT, // various prompts
MSGCH_GOD, // god/religion (param is god)
MSGCH_PRAY, // praying messages (param is god)
MSGCH_DURATION, // effect down/warnings
MSGCH_DANGER, // serious life threats (ie very large HP attacks)
MSGCH_WARN, // much less serious threats
MSGCH_FOOD, // hunger notices
MSGCH_RECOVERY, // recovery from disease/stat/poison condition
MSGCH_SOUND, // messages about things the player hears
MSGCH_TALK, // monster talk (param is monster type)
MSGCH_INTRINSIC_GAIN, // player level/stat/species-power gains
MSGCH_MUTATION, // player gain/lose mutations
MSGCH_MONSTER_SPELL, // monsters casting spells
MSGCH_MONSTER_ENCHANT,// monsters enchantments up and down
MSGCH_MONSTER_DAMAGE, // monster damage reports (param is level)
MSGCH_MONSTER_TARGET, // message marking the monster as a target
MSGCH_ROTTEN_MEAT, // messages about chunks/corpses becoming rotten
MSGCH_EQUIPMENT, // equipment listing messages
MSGCH_FLOOR_ITEMS, // like equipment, but lists of floor items
MSGCH_MULTITURN_ACTION, // delayed action messages
MSGCH_EXAMINE, // messages describing monsters, features, items
MSGCH_EXAMINE_FILTER, // "less important" instances of the above
MSGCH_DIAGNOSTICS, // various diagnostic messages
MSGCH_TUTORIAL, // messages for tutorial
NUM_MESSAGE_CHANNELS // always last
MH_HOLY, // 0 - was -1
MH_NATURAL, // 1 - was 0
MH_UNDEAD, // 2 - was 1
MH_DEMONIC, // 3 - was 2
MH_NONLIVING, // golems and other constructs
MH_PLANT // plants
enum msg_colour_type
{
MSGCOL_BLACK = 0, // the order of these colours is important
MSGCOL_BLUE,
MSGCOL_GREEN,
MSGCOL_CYAN,
MSGCOL_RED,
MSGCOL_MAGENTA,
MSGCOL_BROWN,
MSGCOL_LIGHTGRAY,
MSGCOL_DARKGRAY,
MSGCOL_LIGHTBLUE,
MSGCOL_LIGHTGREEN,
MSGCOL_LIGHTCYAN,
MSGCOL_LIGHTMAGENTA,
MSGCOL_YELLOW,
MSGCOL_WHITE,
MSGCOL_DEFAULT, // use default colour
MSGCOL_ALTERNATE, // use secondary default colour scheme
MSGCOL_MUTED, // don't print messages
MSGCOL_PLAIN // same as plain channel
};
enum misc_item_type
{
MISC_BOTTLED_EFREET, // 0
MISC_CRYSTAL_BALL_OF_SEEING,
MISC_AIR_ELEMENTAL_FAN,
MISC_LAMP_OF_FIRE,
MISC_STONE_OF_EARTH_ELEMENTALS,
MISC_LANTERN_OF_SHADOWS,
MISC_HORN_OF_GERYON,
MISC_BOX_OF_BEASTS,
MISC_CRYSTAL_BALL_OF_ENERGY,
MISC_EMPTY_EBONY_CASKET,
MISC_CRYSTAL_BALL_OF_FIXATION,
MISC_DISC_OF_STORMS,
// pure decks
MISC_DECK_OF_ESCAPE,
MISC_DECK_OF_DESTRUCTION,
MISC_DECK_OF_DUNGEONS,
MISC_DECK_OF_SUMMONING,
MISC_DECK_OF_WONDERS,
MISC_DECK_OF_PUNISHMENT,
// mixed decks
MISC_DECK_OF_WAR,
MISC_DECK_OF_CHANGES,
MISC_DECK_OF_DEFENSE,
MISC_RUNE_OF_ZOT,
NUM_MISCELLANY // mv: used for random generation
};
enum missile_type
{
MI_STONE, // 0
MI_ARROW,
MI_BOLT,
MI_DART,
MI_NEEDLE,
MI_LARGE_ROCK,
MI_SLING_BULLET,
MI_JAVELIN,
MI_THROWING_NET,
NUM_MISSILES,
MI_NONE // was MI_EGGPLANT... used for launch type detection
};
// properties of the monster class (other than resists/vulnerabilities)
enum mons_class_flags
{
M_NO_FLAGS = 0,
M_SPELLCASTER = (1<< 0), // any non-physical-attack powers,
M_ACTUAL_SPELLS = (1<< 1), // monster is a wizard,
M_PRIEST = (1<< 2), // monster is a priest
M_FIGHTER = (1<< 3), // monster is skilled fighter
M_FLIES = (1<< 4), // will crash to ground if paralysed?
M_LEVITATE = (1<< 5), // ... but not if this is set
M_INVIS = (1<< 6), // is created invis
M_SEE_INVIS = (1<< 7), // can see invis
M_SENSE_INVIS = (1<< 8), // can sense invisible things
M_SPEAKS = (1<< 9), // uses talking code
M_CONFUSED = (1<<10), // monster is perma-confused,
M_BATTY = (1<<11), // monster is batty
M_SPLITS = (1<<12), // monster can split
M_AMPHIBIOUS = (1<<13), // monster can swim in water,
M_THICK_SKIN = (1<<14), // monster has more effective AC,
M_HUMANOID = (1<<15), // for Glamour
M_COLD_BLOOD = (1<<16), // susceptible to cold
M_WARM_BLOOD = (1<<17), // no effect currently
M_REGEN = (1<<18), // regenerates quickly
M_BURROWS = (1<<19), // monster digs through rock
M_EVIL = (1<<20), // monster vulnerable to holy spells
M_UNIQUE = (1<<21), // monster is a unique
M_ACID_SPLASH = (1<<22), // Passive acid splash when hit.
M_ARCHER = (1<<23), // gets various archery boosts
M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells?
M_NO_SKELETON = (1<<29), // boneless corpses
M_NO_EXP_GAIN = (1<<31) // worth 0 xp
};
// now saved in an unsigned long.
enum mon_resist_flags
{
MR_NO_FLAGS = 0,
// resistances
// Notes:
// - negative energy is mostly handled via mons_has_life_force()
// - acid is handled mostly by genus (jellies) plus non-living
// - asphyx-resistance replaces hellfrost resistance.
MR_RES_ELEC = (1<< 0),
MR_RES_POISON = (1<< 1),
MR_RES_FIRE = (1<< 2),
MR_RES_HELLFIRE = (1<< 3),
MR_RES_COLD = (1<< 4),
MR_RES_ASPHYX = (1<< 5),
MR_RES_ACID = (1<< 6),
// vulnerabilities
MR_VUL_ELEC = (1<< 7),
MR_VUL_POISON = (1<< 8),
MR_VUL_FIRE = (1<< 9),
MR_VUL_COLD = (1<<10),
// melee armour resists/vulnerabilities
// XXX: how to do combos (bludgeon/slice, bludgeon/pierce)
MR_RES_PIERCE = (1<<11),
MR_RES_SLICE = (1<<12),
MR_RES_BLUDGEON = (1<<13),
MR_VUL_PIERCE = (1<<14),
MR_VUL_SLICE = (1<<15),
MR_VUL_BLUDGEON = (1<<16)
};
};
enum mon_attack_type
{
AT_NONE,
AT_HIT, // including weapon attacks
AT_BITE,
AT_STING,
AT_SPORE,
AT_TOUCH,
AT_ENGULF,
AT_CLAW,
AT_TAIL_SLAP,
AT_BUTT,
AT_SHOOT // attack representing missile damage for M_ARCHER
enum mon_attack_flavour
{
AF_PLAIN,
AF_ACID,
AF_BLINK,
AF_COLD,
AF_CONFUSE,
AF_DISEASE,
AF_DRAIN_DEX,
AF_DRAIN_STR,
AF_DRAIN_XP,
AF_ELEC,
AF_FIRE,
AF_HUNGER,
AF_MUTATE,
AF_BAD_MUTATE,
AF_PARALYSE,
AF_POISON,
AF_POISON_NASTY,
AF_POISON_MEDIUM,
AF_POISON_STRONG,
AF_POISON_STR,
AF_ROT,
AF_VAMPIRIC,
AF_KLOWN,
AF_DISTORT,
AF_RAGE
};
enum mon_event_type
{
ME_EVAL, // 0, evaluate monster AI state
ME_DISTURB, // noisy
ME_ANNOY, // annoy at range
ME_ALERT, // alert to presence
ME_WHACK, // physical attack
ME_SHOT, // attack at range
ME_SCARE, // frighten monster
ME_CORNERED // cannot flee
};
enum mon_dam_level_type
{
MDAM_OKAY,
MDAM_LIGHTLY_DAMAGED,
MDAM_MODERATELY_DAMAGED,
MDAM_HEAVILY_DAMAGED,
MDAM_HORRIBLY_DAMAGED,
MDAM_ALMOST_DEAD,
MDAM_DEAD
};
enum mon_desc_type // things that cross categorical lines {dlb}
{
MDSC_LEAVES_HIDE, // 0
MDSC_REGENERATES,
MDSC_NOMSG_WOUNDS
};
enum mon_holy_type // matches (char) H_foo in mon-util.h, see: monster_holiness()
{
MH_HOLY, // 0 - was -1
MH_NATURAL, // 1 - was 0
MH_UNDEAD, // 2 - was 1
MH_DEMONIC, // 3 - was 2
MH_NONLIVING, // golems and other constructs
MH_PLANT // plants
};
enum mon_intel_type // Must be in increasing intelligence order
{
I_PLANT = 0,
I_INSECT,
I_ANIMAL,
I_NORMAL,
I_HIGH
};
// order of these is important:
enum mon_itemuse_type
{
MONUSE_NOTHING,
MONUSE_EATS_ITEMS,
MONUSE_OPEN_DOORS,
MONUSE_STARTING_EQUIPMENT,
MONUSE_WEAPONS_ARMOUR,
MONUSE_MAGIC_ITEMS
};
};
enum portal_type
{
PORTAL_NONE = 0,
PORTAL_LABYRINTH,
PORTAL_HELL,
PORTAL_ABYSS,
PORTAL_PANDEMONIUM,
NUM_PORTALS
};
// [dshaligram] If you edit potion colours/descriptions, also update
// itemname.cc.
enum potion_description_colour_type
{
PDC_CLEAR,
PDC_BLUE,
PDC_BLACK,
PDC_SILVERY,
PDC_CYAN,
PDC_PURPLE,
PDC_ORANGE,
PDC_INKY,
PDC_RED,
PDC_YELLOW,
PDC_GREEN,
PDC_BROWN,
PDC_PINK,
PDC_WHITE,
PDC_NCOLOURS
};
// [dshaligram] If you edit potion colours/descriptions, also update
// itemname.cc.
enum potion_description_qualifier_type
{
PDQ_NONE,
PDQ_BUBBLING,
PDQ_FUMING,
PDQ_FIZZY,
PDQ_VISCOUS,
PDQ_LUMPY,
PDQ_SMOKY,
PDQ_GLOWING,
PDQ_SEDIMENTED,
PDQ_METALLIC,
PDQ_MURKY,
PDQ_GLUGGY,
PDQ_OILY,
PDQ_SLIMY,
PDQ_EMULSIFIED,
PDQ_NQUALS
enum potion_type
{
POT_HEALING, // 0
POT_HEAL_WOUNDS,
POT_SPEED,
POT_MIGHT,
POT_GAIN_STRENGTH,
POT_GAIN_DEXTERITY, // 5
POT_GAIN_INTELLIGENCE,
POT_LEVITATION,
POT_POISON,
POT_SLOWING,
POT_PARALYSIS, // 10
POT_CONFUSION,
POT_INVISIBILITY,
POT_PORRIDGE,
POT_DEGENERATION,
POT_DECAY, // 15
POT_WATER,
POT_EXPERIENCE,
POT_MAGIC,
POT_RESTORE_ABILITIES,
POT_STRONG_POISON, // 20
POT_BERSERK_RAGE,
POT_CURE_MUTATION,
POT_MUTATION,
POT_BLOOD,
POT_RESISTANCE,
NUM_POTIONS
};
enum proximity_type // proximity to player to create monster
{
PROX_ANYWHERE,
PROX_CLOSE_TO_PLAYER,
PROX_AWAY_FROM_PLAYER,
PROX_NEAR_STAIRS
};
enum randart_prop_type
{
RAP_BRAND, // 0
RAP_AC,
RAP_EVASION,
RAP_STRENGTH,
RAP_INTELLIGENCE,
RAP_DEXTERITY, // 5
RAP_FIRE,
RAP_COLD,
RAP_ELECTRICITY,
RAP_POISON,
RAP_NEGATIVE_ENERGY, // 10
RAP_MAGIC,
RAP_EYESIGHT,
RAP_INVISIBLE,
RAP_LEVITATE,
RAP_BLINK, // 15
RAP_CAN_TELEPORT,
RAP_BERSERK,
RAP_MAPPING,
RAP_NOISES,
RAP_PREVENT_SPELLCASTING, // 20
RAP_CAUSE_TELEPORTATION,
RAP_PREVENT_TELEPORTATION,
RAP_ANGRY,
RAP_METABOLISM,
RAP_MUTAGENIC, // 25
RAP_ACCURACY,
RAP_DAMAGE,
RAP_CURSED,
RAP_STEALTH,
RAP_NUM_PROPERTIES
};
enum read_book_action_type
{
RBOOK_USE_STAFF,
RBOOK_MEMORISE,
RBOOK_READ_SPELL
};
enum run_check_type
{
RCHECK_LEFT,
RCHECK_FRONT,
RCHECK_RIGHT
};
enum run_dir_type
{
RDIR_UP = 0,
RDIR_UP_RIGHT,
RDIR_RIGHT,
RDIR_DOWN_RIGHT,
RDIR_DOWN,
RDIR_DOWN_LEFT,
RDIR_LEFT,
RDIR_UP_LEFT,
RDIR_REST
};
enum run_mode_type
{
RMODE_INTERLEVEL = -4, // Interlevel travel (Ctrl+G)
RMODE_EXPLORE_GREEDY = -3, // Explore + grab items (Tab/Ctrl+I)
RMODE_EXPLORE = -2, // Exploring (Ctrl+O)
RMODE_TRAVEL = -1, // Classic or Plain Old travel
RMODE_NOT_RUNNING = 0, // must remain equal to 0
RMODE_CONTINUE,
RMODE_START,
RMODE_REST_DURATION = 100
};
enum rune_type
{
// Note: that runes DIS-SWAMP have the same numeric value as the branch
RUNE_DIS = BRANCH_DIS,
RUNE_GEHENNA = BRANCH_GEHENNA,
RUNE_COCYTUS = BRANCH_COCYTUS,
RUNE_TARTARUS = BRANCH_TARTARUS,
RUNE_SLIME_PITS = BRANCH_SLIME_PITS,
RUNE_VAULTS = BRANCH_VAULTS,
RUNE_SNAKE_PIT = BRANCH_SNAKE_PIT,
RUNE_ELVEN_HALLS = BRANCH_ELVEN_HALLS, // unused
RUNE_TOMB = BRANCH_TOMB,
RUNE_SWAMP = BRANCH_SWAMP,
RUNE_SHOALS = BRANCH_SHOALS,
// Runes 50 and 51 are for Pandemonium (general demon) and the Abyss
RUNE_DEMONIC = 50,
RUNE_ABYSSAL,
// Runes 60-63 correspond to the Pandemonium demonlords,
// and are equal to the corresponding vault.
RUNE_MNOLEG = 60,
RUNE_LOM_LOBON,
RUNE_CEREBOV,
RUNE_GLOORX_VLOQ,
NUM_RUNE_TYPES, // should always be last
RUNE_NONE
};
};
enum scroll_type
{
SCR_IDENTIFY, // 0
SCR_TELEPORTATION,
SCR_FEAR,
SCR_NOISE,
SCR_REMOVE_CURSE,
SCR_DETECT_CURSE, // 5
SCR_SUMMONING,
SCR_ENCHANT_WEAPON_I,
SCR_ENCHANT_ARMOUR,
SCR_TORMENT,
SCR_RANDOM_USELESSNESS, // 10
SCR_CURSE_WEAPON,
SCR_CURSE_ARMOUR,
SCR_IMMOLATION,
SCR_BLINKING,
SCR_PAPER, // 15
SCR_MAGIC_MAPPING,
SCR_FORGETFULNESS,
SCR_ACQUIREMENT,
SCR_ENCHANT_WEAPON_II,
SCR_VORPALISE_WEAPON, // 20
SCR_RECHARGING,
SCR_ENCHANT_WEAPON_III,
NUM_SCROLLS
enum shout_type
{
S_SILENT, // silent
S_SHOUT, // shout
S_BARK, // bark
S_SHOUT2, // shout twice (e.g. two-headed ogres)
S_ROAR, // roar
S_SCREAM, // scream
S_BELLOW, // bellow (?)
S_SCREECH, // screech
S_BUZZ, // buzz
S_MOAN, // moan
S_WHINE, // irritating whine (mosquito)
S_CROAK, // frog croak
S_GROWL, // for bears
S_HISS, // for snakes and lizards
// Loudness setting for shouts that are only defined in dat/shout.txt
S_VERY_SOFT,
S_SOFT,
S_NORMAL,
S_LOUD,
S_VERY_LOUD,
NUM_SHOUTS,
S_RANDOM
};
};
enum special_armour_type
{
SPARM_NORMAL, // 0
SPARM_RUNNING,
SPARM_FIRE_RESISTANCE,
SPARM_COLD_RESISTANCE,
SPARM_POISON_RESISTANCE,
SPARM_SEE_INVISIBLE, // 5
SPARM_DARKNESS,
SPARM_STRENGTH,
SPARM_DEXTERITY,
SPARM_INTELLIGENCE,
SPARM_PONDEROUSNESS, // 10
SPARM_LEVITATION,
SPARM_MAGIC_RESISTANCE,
SPARM_PROTECTION,
SPARM_STEALTH,
SPARM_RESISTANCE, // 15
SPARM_POSITIVE_ENERGY,
SPARM_ARCHMAGI,
SPARM_PRESERVATION, // 18
SPARM_RANDART_I = 25, // must remain at 25 for now - how high do they go? {dlb}
SPARM_RANDART_II = 26, // 26
SPARM_RANDART_III = 27, // 27
SPARM_RANDART_IV = 28, // 28
SPARM_RANDART_V = 29 // 29 - highest value found thus far {dlb}
};
enum special_missile_type // to separate from weapons in general {dlb}
{
SPMSL_NORMAL, // 0
SPMSL_FLAME, // 1
SPMSL_ICE, // 2
SPMSL_POISONED, // 3
SPMSL_POISONED_II, // 4 - unused
SPMSL_CURARE // 5
};
enum special_room_type
{
SROOM_LAIR_ORC, // 0
SROOM_LAIR_KOBOLD,
SROOM_TREASURY,
SROOM_BEEHIVE,
SROOM_JELLY_PIT,
SROOM_MORGUE,
NUM_SPECIAL_ROOMS // 5 - must remain final member {dlb}
enum brand_type // equivalent to (you.inv[].special or mitm[].special) % 30
{
SPWPN_NORMAL, // 0
SPWPN_FLAMING,
SPWPN_FREEZING,
SPWPN_HOLY_WRATH,
SPWPN_ELECTROCUTION,
SPWPN_ORC_SLAYING, // 5
SPWPN_VENOM,
SPWPN_PROTECTION,
SPWPN_DRAINING,
SPWPN_SPEED,
SPWPN_VORPAL, // 10
SPWPN_FLAME,
SPWPN_FROST,
SPWPN_VAMPIRICISM,
SPWPN_DISRUPTION,
SPWPN_PAIN, // 15
SPWPN_DISTORTION,
SPWPN_REACHING, // 17
SPWPN_RETURNING,
SPWPN_CONFUSE,
SPWPN_RANDART_I = 25, // 25
SPWPN_RANDART_II,
SPWPN_RANDART_III,
SPWPN_RANDART_IV,
SPWPN_RANDART_V,
NUM_SPECIAL_WEAPONS,
SPWPN_DUMMY_CRUSHING, // ONLY TEMPORARY USAGE -- converts to VORPAL
// everything above this point is a special artefact wield:
SPWPN_SINGING_SWORD = 181, // 181
SPWPN_WRATH_OF_TROG,
SPWPN_SCYTHE_OF_CURSES,
SPWPN_MACE_OF_VARIABILITY,
SPWPN_GLAIVE_OF_PRUNE, // 185
SPWPN_SCEPTRE_OF_TORMENT,
SPWPN_SWORD_OF_ZONGULDROK,
// these three are not generated randomly {dlb}
SPWPN_SWORD_OF_CEREBOV,
SPWPN_STAFF_OF_DISPATER,
SPWPN_SCEPTRE_OF_ASMODEUS, // 190
SPWPN_SWORD_OF_POWER,
SPWPN_KNIFE_OF_ACCURACY,
SPWPN_STAFF_OF_OLGREB,
SPWPN_VAMPIRES_TOOTH,
SPWPN_STAFF_OF_WUCAD_MU // 195
};
enum special_wield_type // you.special_wield
{
SPWLD_NONE, // 0
SPWLD_SING,
SPWLD_TROG,
SPWLD_CURSE,
SPWLD_VARIABLE, // 4
SPWLD_PRUNE, // 5 - implicit in it_use3::special_wielded() {dlb}
SPWLD_TORMENT, // 6
SPWLD_ZONGULDROK,
SPWLD_POWER,
SPWLD_WUCAD_MU, // 9
SPWLD_OLGREB, // 10
SPWLD_SHADOW = 50, // 50
SPWLD_NOISE // further differentiation useless -> removed (jpeg)
};
};
enum spflag_type
{
SPFLAG_NONE = 0x0000,
SPFLAG_DIR_OR_TARGET = 0x0001, // use DIR_NONE targeting
SPFLAG_TARGET = 0x0002, // use DIR_TARGET targeting
SPFLAG_GRID = 0x0004, // use DIR_GRID targeting
SPFLAG_DIR = 0x0008, // use DIR_DIR targeting
SPFLAG_TARGETING_MASK = 0x000f, // used to test for targeting
SPFLAG_HELPFUL = 0x0010, // TARG_FRIENDS used
SPFLAG_NOT_SELF = 0x0020, // aborts on isMe
SPFLAG_UNHOLY = 0x0040 // counts at "unholy"
};
enum spret_type
{
SPRET_ABORT = 0, // should be left as 0
SPRET_FAIL,
SPRET_SUCCESS
};
enum spschool_flag_type
{
SPTYP_NONE = 0, // "0" is reserved for no type at all {dlb}
SPTYP_CONJURATION = 1, // was 11, but only for old typematch routine {dlb}
SPTYP_ENCHANTMENT = 1<<1,
SPTYP_FIRE = 1<<2,
SPTYP_ICE = 1<<3,
SPTYP_TRANSMIGRATION = 1<<4,
SPTYP_NECROMANCY = 1<<5,
SPTYP_SUMMONING = 1<<6,
SPTYP_DIVINATION = 1<<7,
SPTYP_TRANSLOCATION = 1<<8,
SPTYP_POISON = 1<<9,
SPTYP_EARTH = 1<<10,
SPTYP_AIR = 1<<11,
SPTYP_HOLY = 1<<12, //jmf: moved to accomodate "random" miscast f/x
SPTYP_LAST_EXPONENT = 12, //jmf: ``NUM_SPELL_TYPES'' kinda useless
NUM_SPELL_TYPES = 14,
SPTYP_RANDOM = 1<<14
};
enum status_redraw_flag_type
{
REDRAW_HUNGER = 0x00000001,
REDRAW_BURDEN = 0x00000002,
REDRAW_LINE_1_MASK = 0x00000003,
REDRAW_PRAYER = 0x00000100,
REDRAW_REPEL_UNDEAD = 0x00000200,
REDRAW_BREATH = 0x00000400,
REDRAW_REPEL_MISSILES = 0x00000800,
REDRAW_REGENERATION = 0x00001000,
REDRAW_INSULATION = 0x00002000,
REDRAW_FLY = 0x00004000,
REDRAW_INVISIBILITY = 0x00008000,
REDRAW_LINE_2_MASK = 0x0000ff00,
REDRAW_CONFUSION = 0x00010000,
REDRAW_POISONED = 0x00020000,
REDRAW_LIQUID_FLAMES = 0x00040000,
REDRAW_DISEASED = 0x00080000,
REDRAW_CONTAMINATED = 0x00100000,
REDRAW_SWIFTNESS = 0x00200000,
REDRAW_SPEED = 0x00400000,
REDRAW_LINE_3_MASK = 0x007f0000
};
enum stave_type
{
// staves
STAFF_WIZARDRY = 0,
STAFF_POWER,
STAFF_FIRE,
STAFF_COLD,
STAFF_POISON,
STAFF_ENERGY,
STAFF_DEATH,
STAFF_CONJURATION,
STAFF_ENCHANTMENT,
STAFF_SUMMONING,
STAFF_AIR,
STAFF_EARTH,
STAFF_CHANNELING,
// rods
STAFF_SMITING, // must be first rod!
STAFF_SPELL_SUMMONING,
STAFF_DESTRUCTION_I,
STAFF_DESTRUCTION_II,
STAFF_DESTRUCTION_III,
STAFF_DESTRUCTION_IV,
STAFF_WARDING,
STAFF_DISCOVERY,
STAFF_DEMONOLOGY,
STAFF_STRIKING,
STAFF_VENOM,
NUM_STAVES // must remain last member {dlb}
};
// beam[].type - note that this (and its variants) also accepts values from other enums - confusing {dlb}
enum zap_symbol_type
{
SYM_SPACE = ' ', // 32
SYM_FLASK = '!', // 33
SYM_BOLT = '#', // 35
SYM_CHUNK = '%', // 37
SYM_OBJECT = '(', // 40 - actually used for books, but... {dlb}
SYM_WEAPON = ')', // 41
SYM_ZAP = '*', // 42
SYM_BURST = '+', // 43
SYM_STICK = '/', // 47
SYM_TRINKET = '=', // 61
SYM_SCROLL = '?', // 63
SYM_DEBUG = 'X', // 88
SYM_ARMOUR = '[', // 91
SYM_MISSILE = '`', // 96
SYM_EXPLOSION = '#'
};
enum tag_type // used during save/load process to identify data blocks
{
TAG_VERSION = 0, // should NEVER be read in!
TAG_YOU = 1, // 'you' structure
TAG_YOU_ITEMS, // your items
TAG_YOU_DUNGEON, // dungeon specs (stairs, branches, features)
TAG_LEVEL, // various grids & clouds
TAG_LEVEL_ITEMS, // items/traps
TAG_LEVEL_MONSTERS, // monsters
TAG_GHOST, // ghost
TAG_LEVEL_ATTITUDE, // monster attitudes
TAG_LOST_MONSTERS, // monsters in transit
NUM_TAGS
enum tag_file_type // file types supported by tag system
{
TAGTYPE_PLAYER=0, // Foo.sav
TAGTYPE_LEVEL, // Foo.00a, .01a, etc.
TAGTYPE_GHOST, // bones.xxx
TAGTYPE_PLAYER_NAME // Used only to read the player name
};
enum transformation_type
{
TRAN_NONE, // 0
TRAN_SPIDER,
TRAN_BLADE_HANDS,
TRAN_STATUE,
TRAN_ICE_BEAST,
TRAN_DRAGON, // 5
TRAN_LICH,
TRAN_SERPENT_OF_HELL,
TRAN_AIR,
TRAN_BAT,
NUM_TRANSFORMATIONS // must remain last member {dlb}
};
enum unarmed_attack_type
{
UNAT_NO_ATTACK, // 0
UNAT_KICK,
UNAT_HEADBUTT,
UNAT_TAILSLAP,
UNAT_PUNCH,
UNAT_BITE
};
};
enum vorpal_damage_type
{
// Types of damage a weapon can do... currently assuming that anything
// with BLUDGEON always does "AND" with any other specified types,
// and and sets not including BLUDGEON are "OR".
DAM_BASH = 0x0000, // non-melee weapon blugeoning
DAM_BLUDGEON = 0x0001, // crushing
DAM_SLICE = 0x0002, // slicing/chopping
DAM_PIERCE = 0x0004, // stabbing/piercing
DAM_WHIP = 0x0008, // whip slashing (no butcher)
// These are used for vorpal weapon desc (don't set more than one)
DVORP_NONE = 0x0000, // used for non-melee weapons
DVORP_CRUSHING = 0x1000,
DVORP_SLICING = 0x2000,
DVORP_PIERCING = 0x3000,
DVORP_CHOPPING = 0x4000, // used for axes
DVORP_SLASHING = 0x5000, // used for whips
DVORP_STABBING = 0x6000, // used for knives/daggers
DVORP_CLAWING = 0x7000, // claw damage
// These are shortcuts to tie vorpal/damage types for easy setting...
// as above, setting more than one vorpal type is trouble.
DAMV_NON_MELEE = DVORP_NONE | DAM_BASH, // launchers
DAMV_CRUSHING = DVORP_CRUSHING | DAM_BLUDGEON,
DAMV_SLICING = DVORP_SLICING | DAM_SLICE,
DAMV_PIERCING = DVORP_PIERCING | DAM_PIERCE,
DAMV_CHOPPING = DVORP_CHOPPING | DAM_SLICE,
DAMV_SLASHING = DVORP_SLASHING | DAM_WHIP,
DAMV_STABBING = DVORP_STABBING | DAM_PIERCE,
DAM_MASK = 0x0fff, // strips vorpal specification
DAMV_MASK = 0xf000 // strips non-vorpal specification
};
// NOTE: This order is very special! Its basically the same as ZAP_*,
// and there are bits of the code that still use that fact.. see zap_wand().
enum wand_type // mitm[].subtype
{
WAND_FLAME, // 0
WAND_FROST,
WAND_SLOWING,
WAND_HASTING,
WAND_MAGIC_DARTS,
WAND_HEALING, // 5
WAND_PARALYSIS,
WAND_FIRE,
WAND_COLD,
WAND_CONFUSION,
WAND_INVISIBILITY, // 10
WAND_DIGGING,
WAND_FIREBALL,
WAND_TELEPORTATION,
WAND_LIGHTNING,
WAND_POLYMORPH_OTHER, // 15
WAND_ENSLAVEMENT,
WAND_DRAINING,
WAND_RANDOM_EFFECTS,
WAND_DISINTEGRATION,
NUM_WANDS // must remain last member {dlb}
};
enum weapon_type
{
// Base weapons
WPN_CLUB, // 0
WPN_MACE,
WPN_FLAIL,
WPN_DAGGER,
WPN_MORNINGSTAR,
WPN_SHORT_SWORD, // 5
WPN_LONG_SWORD,
WPN_GREAT_SWORD,
WPN_SCIMITAR,
WPN_HAND_AXE,
WPN_BATTLEAXE, // 10
WPN_SPEAR,
WPN_HALBERD,
WPN_SLING,
WPN_BOW,
WPN_CROSSBOW, // 15
WPN_HAND_CROSSBOW,
WPN_GLAIVE,
WPN_QUARTERSTAFF,
// these three not created ordinarily
WPN_SCYTHE,
WPN_GIANT_CLUB, // 20
WPN_GIANT_SPIKED_CLUB,
// "rare" weapons - some have special cases and are uncommon
WPN_EVENINGSTAR,
WPN_QUICK_BLADE,
WPN_KATANA,
WPN_EXECUTIONERS_AXE, // 25
WPN_DOUBLE_SWORD,
WPN_TRIPLE_SWORD,
WPN_HAMMER,
WPN_ANCUS,
WPN_WHIP, // 30
WPN_SABRE,
WPN_DEMON_BLADE,
WPN_DEMON_WHIP,
WPN_DEMON_TRIDENT,
WPN_BROAD_AXE, // 35
// base items (continued)
WPN_WAR_AXE,
WPN_TRIDENT,
WPN_SPIKED_FLAIL,
WPN_GREAT_MACE,
WPN_DIRE_FLAIL, // 40
WPN_KNIFE,
WPN_BLOWGUN,
WPN_FALCHION,
WPN_BLESSED_BLADE, // 44
WPN_LONGBOW,
WPN_LAJATANG,
WPN_LOCHABER_AXE,
NUM_WEAPONS, // 48 - must be last regular member {dlb}
// special cases
WPN_UNARMED = 500, // 500
WPN_UNKNOWN = 1000, // 1000
WPN_RANDOM
};
enum weapon_description_type
{
DWPN_PLAIN = 0, // 0 - added to round out enum {dlb}
DWPN_RUNED = 1, // 1
DWPN_GLOWING,
DWPN_ORCISH,
DWPN_ELVEN,
DWPN_DWARVEN // 5
enum weapon_property_type
{
PWPN_DAMAGE, // 0
PWPN_HIT,
PWPN_SPEED,
PWPN_ACQ_WEIGHT
};
enum zap_type
{
ZAP_FLAME, // 0
ZAP_FROST,
ZAP_SLOWING,
ZAP_HASTING,
ZAP_MAGIC_DARTS,
ZAP_HEALING, // 5
ZAP_PARALYSIS,
ZAP_FIRE,
ZAP_COLD,
ZAP_CONFUSION,
ZAP_INVISIBILITY, // 10
ZAP_DIGGING,
ZAP_FIREBALL,
ZAP_TELEPORTATION,
ZAP_LIGHTNING,
ZAP_POLYMORPH_OTHER, // 15
ZAP_VENOM_BOLT,
ZAP_NEGATIVE_ENERGY,
ZAP_CRYSTAL_SPEAR,
ZAP_BEAM_OF_ENERGY,
ZAP_MYSTIC_BLAST, // 20
ZAP_ENSLAVEMENT,
ZAP_PAIN,
ZAP_STICKY_FLAME,
ZAP_DISPEL_UNDEAD,
ZAP_CLEANSING_FLAME, // 25
ZAP_BONE_SHARDS,
ZAP_BANISHMENT,
ZAP_DEGENERATION,
ZAP_STING,
ZAP_HELLFIRE, // 30
ZAP_IRON_BOLT,
ZAP_STRIKING,
ZAP_STONE_ARROW,
ZAP_ELECTRICITY,
ZAP_ORB_OF_ELECTRICITY, // 35
ZAP_SPIT_POISON,
ZAP_DEBUGGING_RAY,
ZAP_BREATHE_FIRE,
ZAP_BREATHE_FROST,
ZAP_BREATHE_ACID, // 40
ZAP_BREATHE_POISON,
ZAP_BREATHE_POWER,
ZAP_ENSLAVE_UNDEAD,
ZAP_AGONY,
ZAP_DISRUPTION, // 45
ZAP_DISINTEGRATION, // 46
// ZAP_ISKS_CROSS, // 47: Isk's Cross -- commented out, deprecated {dlb}
ZAP_BREATHE_STEAM = 48, // 48
ZAP_CONTROL_DEMON,
ZAP_ORB_OF_FRAGMENTATION, // 50
ZAP_ICE_BOLT,
ZAP_ICE_STORM,
ZAP_BACKLIGHT, //jmf: added next bunch 19mar2000
ZAP_SLEEP,
ZAP_FLAME_TONGUE,
ZAP_SANDBLAST,
ZAP_SMALL_SANDBLAST,
ZAP_MAGMA,
ZAP_POISON_ARROW,
ZAP_BREATHE_STICKY_FLAME,
ZAP_BREATHE_LIGHTNING,
ZAP_PETRIFY,
ZAP_HELLFROST,
NUM_ZAPS // must remain last member {dlb}
};
enum zap_count_type
{
ZAPCOUNT_EMPTY = -1,
ZAPCOUNT_UNKNOWN = -2
};
enum zombie_size_type
{
Z_NOZOMBIE,
Z_SMALL,
Z_BIG
};
struct crawl_view_geometry
{
public:
coord_def termsz; // Size of the terminal.
coord_def viewp; // Left-top pos of viewport.
coord_def viewsz; // Size of the viewport (play area).
coord_def hudp; // Left-top pos of status area.
coord_def hudsz; // Size of the status area.
coord_def msgp; // Left-top pos of the message pane.
coord_def msgsz; // Size of the message pane.
coord_def vgrdc; // What grid pos is at the centre of the view
// usually you.pos().
coord_def viewhalfsz;
coord_def glos1, glos2; // LOS limit grid coords (inclusive)
coord_def vlos1, vlos2; // LOS limit viewport coords (inclusive)
coord_def mousep; // Where the mouse is.
static const int message_min_lines = 7;
static const int hud_min_width = 41;
static const int hud_min_gutter = 3;
static const int hud_max_gutter = 6;
private:
coord_def last_player_pos;
public:
crawl_view_geometry();
void init_geometry();
void init_view();
void set_player_at(const coord_def &c, bool force_centre = false);
coord_def view_centre() const
{
return viewp + viewhalfsz;
}
bool in_grid_los(const coord_def &c) const
{
return (c.x >= glos1.x && c.x <= glos2.x
&& c.y >= glos1.y && c.y <= glos2.y);
}
bool in_view_los(const coord_def &c) const
{
return (c.x >= vlos1.x && c.x <= vlos2.x
&& c.y >= vlos1.y && c.y <= vlos2.y);
}
bool in_view_viewport(const coord_def &c) const
{
return (c.x >= viewp.x && c.y >= viewp.y
&& c.x < viewp.x + viewsz.x
&& c.y < viewp.y + viewsz.y);
}
bool in_grid_viewport(const coord_def &c) const
{
return in_view_viewport(c - vgrdc + view_centre());
}
};
extern crawl_view_geometry crawl_view;
// output from direction() function:
struct dist
{
bool isValid; // valid target chosen?
bool isTarget; // target (true), or direction (false)?
bool isMe; // selected self (convenience: tx == you.x_pos,
// ty == you.y_pos)
bool isEndpoint; // Does the player want the attack to stop at (tx,ty)?
bool isCancel; // user cancelled (usually <ESC> key)
bool choseRay; // user wants a specific beam
int tx,ty; // target x,y or logical extension of beam to map edge
int dx,dy; // delta x and y if direction - always -1,0,1
ray_def ray; // ray chosen if necessary
// internal use - ignore
int prev_target; // previous target
// target - source (source == you.pos())
coord_def target() const
{
return coord_def(tx, ty);
}
};
struct monsters;
struct ait_hp_loss;
enum activity_interrupt_payload_type
{
AIP_NONE,
AIP_INT,
AIP_STRING,
AIP_MONSTER,
AIP_HP_LOSS
};
struct activity_interrupt_data
{
activity_interrupt_payload_type apt;
const void *data;
std::string context;
activity_interrupt_data()
: apt(AIP_NONE), data(NULL), context()
{
}
activity_interrupt_data(const int *i)
: apt(AIP_INT), data(i), context()
{
}
activity_interrupt_data(const char *s)
: apt(AIP_STRING), data(s), context()
{
}
activity_interrupt_data(const std::string &s)
: apt(AIP_STRING), data(s.c_str()), context()
{
}
activity_interrupt_data(const monsters *m, const std::string &ctx = "")
: apt(AIP_MONSTER), data(m), context(ctx)
{
}
activity_interrupt_data(const ait_hp_loss *ahl)
: apt(AIP_HP_LOSS), data(ahl), context()
{
}
activity_interrupt_data(const activity_interrupt_data &a)
: apt(a.apt), data(a.data), context(a.context)
{
}
};
struct ait_hp_loss
{
int hp;
int hurt_type; // KILLED_BY_POISON, etc.
bool is_deck(const item_def &item)
{
return item.base_type == OBJ_MISCELLANY
&& (item.sub_type >= MISC_DECK_OF_ESCAPE &&
item.sub_type <= MISC_DECK_OF_DEFENSE);
}
deck_rarity_type deck_rarity(const item_def &item)
{
ASSERT( is_deck(item) );
switch (item.colour)
{
case BLACK: case BLUE: case GREEN: case CYAN: case RED:
default:
return DECK_RARITY_COMMON;
case MAGENTA: case BROWN:
return DECK_RARITY_RARE;
case LIGHTMAGENTA:
return DECK_RARITY_LEGENDARY;
}
}
class input_history
{
public:
input_history(size_t size);
void new_input(const std::string &s);
void clear();
const std::string *prev();
const std::string *next();
void go_end();
private:
typedef std::list<std::string> string_list;
string_list history;
string_list::iterator pos;
size_t maxsize;
};
enum item_origin_dump_selector
{
IODS_PRICE = 0, // Extra info is provided based on price
IODS_ARTEFACTS = 1, // Extra information on artefacts
IODS_EGO_ARMOUR = 2,
IODS_EGO_WEAPON = 4,
IODS_JEWELLERY = 8,
IODS_RUNES = 16,
IODS_RODS = 32,
IODS_STAVES = 64,
IODS_BOOKS = 128,
IODS_EVERYTHING = 0xFF
};
enum demon_beam_type
{
DMNBM_HELLFIRE, // 0
DMNBM_SMITING,
DMNBM_BRAIN_FEED,
DMNBM_MUTATION
};
// beam[].type - note that this (and its variants) also accepts values
// from other enums - confusing {dlb}
enum zap_symbol_type
{
SYM_SPACE = ' ', // 32
SYM_FLASK = '!', // 33
SYM_BOLT = '#', // 35
SYM_CHUNK = '%', // 37
SYM_OBJECT = '(', // 40 - actually used for books, but... {dlb}
SYM_WEAPON = ')', // 41
SYM_ZAP = '*', // 42
SYM_BURST = '+', // 43
SYM_STICK = '/', // 47
SYM_TRINKET = '=', // 61
SYM_SCROLL = '?', // 63
SYM_DEBUG = 'X', // 88
SYM_ARMOUR = '[', // 91
SYM_MISSILE = '`', // 96
SYM_EXPLOSION = '#'
};
enum zap_type
{
ZAP_FLAME, // 0
ZAP_FROST,
ZAP_SLOWING,
ZAP_HASTING,
ZAP_MAGIC_DARTS,
ZAP_HEALING, // 5
ZAP_PARALYSIS,
ZAP_FIRE,
ZAP_COLD,
ZAP_CONFUSION,
ZAP_INVISIBILITY, // 10
ZAP_DIGGING,
ZAP_FIREBALL,
ZAP_TELEPORTATION,
ZAP_LIGHTNING,
ZAP_POLYMORPH_OTHER, // 15
ZAP_VENOM_BOLT,
ZAP_NEGATIVE_ENERGY,
ZAP_CRYSTAL_SPEAR,
ZAP_BEAM_OF_ENERGY,
ZAP_MYSTIC_BLAST, // 20
ZAP_ENSLAVEMENT,
ZAP_PAIN,
ZAP_STICKY_FLAME,
ZAP_DISPEL_UNDEAD,
ZAP_CLEANSING_FLAME, // 25
ZAP_BONE_SHARDS,
ZAP_BANISHMENT,
ZAP_DEGENERATION,
ZAP_STING,
ZAP_HELLFIRE, // 30
ZAP_IRON_BOLT,
ZAP_STRIKING,
ZAP_STONE_ARROW,
ZAP_ELECTRICITY,
ZAP_ORB_OF_ELECTRICITY, // 35
ZAP_SPIT_POISON,
ZAP_DEBUGGING_RAY,
ZAP_BREATHE_FIRE,
ZAP_BREATHE_FROST,
ZAP_BREATHE_ACID, // 40
ZAP_BREATHE_POISON,
ZAP_BREATHE_POWER,
ZAP_ENSLAVE_UNDEAD,
ZAP_AGONY,
ZAP_DISRUPTION, // 45
ZAP_DISINTEGRATION, // 46
// ZAP_ISKS_CROSS, // 47: Isk's Cross -- commented out, deprecated {dlb}
ZAP_BREATHE_STEAM = 48, // 48
ZAP_CONTROL_DEMON,
ZAP_ORB_OF_FRAGMENTATION, // 50
ZAP_ICE_BOLT,
ZAP_ICE_STORM,
ZAP_BACKLIGHT, //jmf: added next bunch 19mar2000
ZAP_SLEEP,
ZAP_FLAME_TONGUE,
ZAP_SANDBLAST,
ZAP_SMALL_SANDBLAST,
ZAP_MAGMA,
ZAP_POISON_ARROW,
ZAP_BREATHE_STICKY_FLAME,
ZAP_BREATHE_LIGHTNING,
ZAP_PETRIFY,
ZAP_HELLFROST,
NUM_ZAPS // must remain last member {dlb}
};
struct dist;
struct bolt
{
// INPUT parameters set by caller
int range; // minimum range
int rangeMax; // maximum range
int type; // missile gfx
int colour;
int flavour;
int source_x, source_y; // beam origin
dice_def damage;
int ench_power, hit;
int target_x, target_y; // intended target
char thrower; // what kind of thing threw this?
char ex_size; // explosion radius (0==none)
int beam_source; // NON_MONSTER or monster index #
std::string name;
bool is_beam; // beams? (can hits multiple targets?)
bool is_explosion;
bool is_big_cloud; // expands into big_cloud at endpoint
bool is_enchant; // no block/dodge, but mag resist
bool is_energy; // mostly energy/non-physical attack
bool is_launched; // was fired from launcher?
bool is_thrown; // was thrown from hand?
bool target_first; // targeting by direction
bool aimed_at_spot; // aimed at (x,y), should not cross
std::string aux_source; // source of KILL_MISC beams
// OUTPUT parameters (tracing, ID)
bool obvious_effect; // did an 'obvious' effect happen?
bool effect_known; // did we _know_ this would happen?
int fr_count, foe_count; // # of times a friend/foe is "hit"
int fr_power, foe_power; // total levels/hit dice affected
// INTERNAL use - should not usually be set outside of beam.cc
bool is_tracer; // is this a tracer?
bool aimed_at_feet; // this was aimed at self!
bool msg_generated; // an appropriate msg was already mpr'd
bool in_explosion_phase; // explosion phase (as opposed to beam phase)
bool smart_monster; // tracer firer can guess at other mons. resists?
bool can_see_invis; // tracer firer can see invisible?
mon_attitude_type attitude; // attitude of whoever fired tracer
int foe_ratio; // 100* foe ratio (see mons_should_fire())
bool chose_ray; // do we want a specific ray?
ray_def ray; // shoot on this specific ray
public:
// A constructor to try and fix some of the bugs that occur because
// this struct never seems to be properly initialized. Definition
// is over in beam.cc.
bolt();
void set_target(const dist &);
// Returns YOU_KILL or MON_KILL, depending on the source of the beam.
killer_type killer() const;
coord_def target() const
{
return (coord_def(target_x, target_y));
}
};
enum ability_flag_type
{
ABFLAG_NONE = 0x00000000,
ABFLAG_BREATH = 0x00000001, // ability uses DUR_BREATH_WEAPON
ABFLAG_DELAY = 0x00000002, // ability has its own delay (ie glamour)
ABFLAG_PAIN = 0x00000004, // ability must hurt player (ie torment)
ABFLAG_EXHAUSTION = 0x00000008, // fails if you.exhausted
ABFLAG_INSTANT = 0x00000010, // doesn't take time to use
ABFLAG_PERMANENT_HP = 0x00000020, // costs permanent HPs
ABFLAG_PERMANENT_MP = 0x00000040, // costs permanent MPs
ABFLAG_CONF_OK = 0x00000080 // can use even if confused.
};