git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6550 c06c8d41-db1a-0410-9941-cceddc491573
Q3B3UVMYEVC4YJUPYVSNTR4DJH4E6J4JJDHZNT5LNOCHCPPMEMXAC MN4TJZVTK27PM5ETQBJBUMF64CXJRN75IVCS2MWGTIVCFPRR7LOAC I2G7DP3TJL4RDMYKNXAA67P3VRSO3RF7FHZWA5CYINSEWEQE2YSQC MWS346AS2OCQYDQ64HRT3U47NJCRGEYBLMT5K7DWSWT7ULMA4WLAC BWPT5FA3JZJCSFPPRDLJF76ZKAG4WGUHNIWQFAYZ4DAZLFIIMZ7AC KHY3KA2VB4VVMKYNR7ETQQBT2NO2LTEQQPBRQ7TA6O4BNH7OLVYQC XWJFLTFZL3MPBNI6Q3VEKRY45PVTHGTQUNLVFMP2FVI7LBZJQ2XQC 66KRMFZAWM65VI75Z6O4CIVCKB3Z2YQCQSGE44OAP6ESTEFUWYOQC BGPUXHZ2FDUKA6LAFNBDQJOT3XQGTZQDYBPU7Z6H5HTXZK2EG2BAC MZFGNRIWJAKU2LX5S2C76IRT4ORXSBXBNP24EUSFEZYHUVIS3A5QC RLKCTCTFWIGLVMMXGD4IXXA7HCKLOJ3KILVWQUMWVT2CNI5ZMRPAC 325MMZ56C7O4XJSIVKTRHWL2Z5FUVVXATBE7PEHXZGX4XXR2NOJQC OYPZUHLG34Y64LSNG3G4GTCOZJWV2JOLKWFDUMVRAVFXKXUERPEQC 3YAYJNECJUGIKFNE4F5QJ2X3PRIEIACYXUQL45EHVLROMK6NJOOQC I4M3O5UA4UOV35WFD435G3GP6RT3EZ5NPRZ645X22A2Z7CR2E2AAC KVPISK262B2GBNOFBAA3GL3QUNAJJGKVS326YYQZTP7QF3YKFX4QC 5JMTXGN7S5VCLCXRYJAOV32MPPW4IECFJ2NCSFLDVRNFPINHPDTQC KDSO4JU27HHHNK4PMAFCE2GULZ5X4J2R5SYMTXC4I6YALWYBB4UAC T6IYM4SLLV3G55XKSFPK3QAY2KF6MXYXXHLFHGLEQEZABTCJU6UAC 2KZ65CC2GFWTSCYVXFSKNRW3CJBBYPSWE2F7XFFI2OXH4I2YOA4AC EQNA77UM24FFYQ2N44FG53KQGLS43ZGEX7XS5UWR6MM2HE3JBKAAC AMSENYIGRJWHHGHLKIZQGZZQTWCZBTS2Y3WKPVTZZRI7ZMTATBCAC AEPGJLX47SNMG4B25UWQXXIQTN4N7TCIVSENYVYAJEQFPTT2OP6AC 55OQMLV7ONCBKOS4KW6W4D3X7JZZTI3PGIVUVHCWCLWCPGKTEE4AC OHOFJZ6S5AJUO5EFVGG7HJHRPSXJSTJD2DDXAERT4LNVWDK23K6AC 72YQQHCY6DYHOVZ6P5C7APPDA7D4UUPJTBJCLRSK7RIKLBP5JS4AC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC AXAM3TX4CUCIPL6ILEJLGJ4D4SMCJYDXGLIB256PBQXXKBIKZ4QAC JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC D5EMJEEIJSSULF236DUM26QHHNDLH7FXAOBHFDAYI65KCKTDTDYQC IHOKNI4O7EEW4UBMKHP6XOZNEIQSW4AYOT4O3JXUIXNNR553IQAQC 5DTGRF4G4T2CAUCZHTPNM6FF2XJHUYMWF74MATNVJC5QYSOPNOPQC 5B5DP5S6A6LQMKZYVLQAEMHQZWFWYDHPCKQGRNSCNNYIBQYZ6BIQC S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC MZLB3Q7G4EC2BR3OFMG55WPHXPFJGQSLWAIHHFJEAEATPUTYR7EAC S6Z5DI4LGLFHRSOVGGC7PW5CPP34GR5TJXPSJ2XMBFR5YU6VNF4QC YBNWH7EXICXYJXYSLYSVMVZCVR7MWMVJ24CAUZ4ELPZUYTJ4CE5AC BLZC4APKXT76IVDHJ7UHBZQJJVW4FOLLDEDAKAGNLF6LZYMWOWOAC XR2332MJV6ZC6GWBRRWV4IZAYXMK7WLXGSNLGZHHAKN65HS26IVAC M5JRISNFA35UTUE6EZKABYLNFLD5Y2CM3CEASFEWM4QRNYC3UK3QC HRAL36C7UUL7V6TFXQ76FZ3VVVFEJYF7YWOP2EXYXP6C27XME2PAC LJNAKLI5N7MDAOOM6RSRUOJ6OOKRAM7NHA3G562KYAVN6H4Y3R4QC 5FA5IEAXTMXYS2VUBVDKBKHPKAIOY4GN5SXYJORBYWQIGHVW3FFQC H5CCPXNHFSQ3SBRGB72XZTFD2U77DP7ZMW2SXXKD7DD3EO732QDQC C4WXQRJTDW53PYFWQ4LOINSCI2IWMIQTH5WDSI7QUP72PKDBYHZAC ANOEQTM6IGCBTESKKQ5PCBSDTZ7VGRCMDIOAFEH4R7DJHKWKDFAAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC PL6I2CMSTHY5ZHWVMIQE5YTM5S5VPKBNZM6QJVHZSSKOJGIJ5W4AC D27U7RT2C77NEUBP6JCSQJ2DRCJVHOXUO2PFZ45VFYMEVMKI4TSAC L57WEZMVIHTFRLWVIPWOIOWHCF2I53TVUVYJ2V6IZ64R56FVTZZAC NG53L53MSFQZAIVKHG54IEMXNJ33AYVPF2OZM4MMJFDKEJCGPBSAC AUXVWXWIFSTWFA6VZXN2FMG7FQEKRZVV6MD32VQQ7J2RKCXHAVGAC 4VK7VHWRVRO66BRSGTBPSYJGGXLRF6AG6G74UDTPHTPXR7ZRNINQC E7DV36ZR6TOGBD75BHGARCMIQQS6MSV7V3A7M7V4LOFHEC5NF6CQC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC 75M6AVUSS3G5EJECJJRB67V5UYDOIV26FZNB2FFCMBZ33EK7FVIQC Z7SNXEH74EM5YJW3KVPVDQAQZB425M62AYB5GODBNVYMBRVJ4LSQC XHNJ2W4AQHIF32P2ENIMMDLWAIFWP442KJIZC6RKS4HBJNZIHHBAC HKMVHUQLTDIDM3HGXCTLPHHT5YJHV5UMQPEVX5ZL4G7OLEICIOXQC WHY6LRRJ5T2NSBE3IUCR4X3TOAH7TTK5NPUPUIFT7TPNJ6J4HBDAC 4HATGRJJE7Q6LXHJ3ZGYTNBLG542KAUEK6ERKARIYRKRWY6VTDKQC CQ24AVAI6SW3AHTIDMLPSTRRBEU6FHRF5I5FD6G5QIYE6PO4BQMQC TPZWAV3USKO7RX4IGHLZKVPRN36K33PJPSZYL6FZMX4XBHTYOQYAC 2TECJQA3PK7OYSSTOWZSQFWMTATJRHHA6JV3IGRHFGS3R7U27RZAC 7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC ESWIM76FGJL4QFLSHU6AC4D74PT7OPLQ7ZCJYWLZS5UCBAJDXYHAC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC HQTS3VQ6PNUZKHNVEWMML7JNAAAKL4DSW3KFSRCCSLGYTDHZFCCAC 7HA2754QW3SBCAJ5K6KUXNXXXIZB5BIBCFPLXADCXHH6EREKXHSAC TOOHYAX73C5KPSWGHPCBWCUN62WMMO3BI5CWEEMGV3WBFZ5RIH5AC W54GZBNFKPOF6DTOVK73PVASTQI5DXG42WQ6CXFDPXHFZOHUVVSQC NK2TBKWOQBD2ZRGAO4Z3HMZPIN7UX3HNUS2YHEIJUUINUTRMPODQC LS5XCCGKQHSJQGWLWLGTP2F5OYWK4ND5AQQAGRN6H2HVBSXNCCZAC 5HF63O5IRRERI2V3SZEDHUNFHUF2B4RSVWQR6C6DR5JF5UYSROWAC QXD3HX6QQ37PW6HVKIIKGFLO2ACROLUGKK66KFX7ED6SO4FDXB2AC RS2Q66UPKG2NLNBE6UMX273UEVNGTNLVEITB2PCRVHZWTS2WXTAQC OYYZVCE3QHBVJM6IEKK5HTJRG5YOVQNCBRMSJENTHOI2WPJLNCFAC GWGKGHFGBLVPDSSDWYFORHZHMWOR3SFC5PJNF732V7FEKWWJKPOAC O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC KZIHM6RUX43HHKXG6HGJHVEEYUPVVNBFIWMT4SKPD2GAH5ZMA3KAC 3SK2OEKJBQUGGYU2PJ7BWBGMKS53K2JH6HKL65AWTFN6JVZRG2PAC 44LY6TB272RWWFLON2XOUIXWFPUXM5OMX6KLX66HH37BNURVT4DQC 4SUUJM2DQUEWHDG3UKJUDZABLHFVF2CFUX5GVAWKT7BBBGR2ISTQC U6ILMKBXTQZYT62IGD2CALYNU4VQGRSTHN6QBFBU7BVUBHWYOEQQC HUMRQOA7Y32XBXQNR5LUIWM2ZB57XDW4ZQHMZ4RDGDZATY6K73SQC CSRWDG2SUGS4YR4PAFI574EGEXW65P6JDT4ZHWDICS2G2GZIGEUQC D7EPLNYHJH6C4CTMHCOUUODKGHCJRE4CGKNVSCHCSABN6ZOD2ZBAC J3M6J3UPL4AUJDXINY7UKH2JZQVQLKGH7AMOKI6L3QI7Y2F33O5QC LP5EK64IEM7AHNYQID4GGKOQJQNZLKY4DCCZN47SIUZ6IXAXH5UAC CKY7MRFWMNHXIPJD5ZUAJN5T2YHUIEAYBNYYV5GN74LBZJRDJMEQC HODV46TCH5AGI42Z5JKVDX4VCRVQCNREJUL6W3TUJK6S77SXQNLQC RB4PNFZOBEPUJM6PH4J4IPKF2WYYSQ2DINHZHOGDPA4ZN6E4RJAAC E3X5HVN5UN75OMTJA6JFQBNZ54P37NDZLZZF7EFBZZC45KR73YGAC Q3XHNSHW6FI4JCXSEABATRFBJPMCF7PXNG2K6ZQTRRPVMIZFHUBQC 3FRPKD2JSN7RA2HKWAO3XV7MMKCIAMWIMU6JNJ452VZEUSXM6PWQC FOQJ5S5WR7P7YMEWQ5Q4O7LTGLQ7LFVM4I2SG2Q7MIVC4PB2JHTQC OEISFRW2B7E4YRJSWXNXBH2IAJO4O3LHNYFPFD3MBY57LYVRHMZQC MQOL2SN2EYBCAVVJ7NPCXEV6C4NPBNMC6QD2AOTZPIAZB243JQ7QC JXAB5WYRDGBLKOBEQJLZKIE7YHQ2ZI6LKWEFSNF2TGAHPNUI3SBQC ZNUMGZOGREVG6RNSM4RGHG2Y6NYL7O2U642V6F3HJAXMTC5JXJHAC ZWVXM43CBKDWRFNZ432Z6G6J7DBA2GKRRGCSZQCRQS2M4YX53ETQC ZBHENBGH5RNIC4L2NP45RJWYB3256NAM2JU2E3CD2RF6FEV4Z4FAC HBHQQDULNVWISJ75XIL6R6BFEDYRNY22NX3ZTFVNP5ZWJGJSKOEQC RNRDGY5JBFBHF7IDQ6LDV2GULR4ILNJ7UHYNGIWZIPLN6IJYX2PQC CD4GR4YLJMAMP5XZ3IR7MZ6SDLQJL6YSPWMH74VV5Z56TZAZDM2QC TZLAHS2FQGDWDAO6OQFZIZALQCCRTCRBJZBNZFNQ4G7D5UYAIFQAC QON6K747RDVN55UTIJWNGIIGSDS7IHKB24JMHWSIMAQ572D7C3NAC 3ICSXUKO2RWAARVKXTV3MGIB6G7UQHIHN5I4JNBLXIFEQA4H462QC PDOFPXD2X6VI23AHKCGQ5RVDBG74CNP2E3YOHKXLOARHHBXEK3HQC TUF6IG4NNHW5YD5AVRYE7GILPSFJLUV6442F5LSP436MFEIIGVUAC 3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC TFHMBVXTRA2LXBHE7L7OEWK37JQN5DWZ3HOACMN7PRWVJNCS4TYQC OTVV4KBC5LVECK5B2Y7ORMRV7K4OXRZMYPCAMWJCUGZCQIBVRTXQC GJIMGW6UJFIEZEOOHUVR6647W2C3L6MFRKIE5AKQIPZ5LIOWZWMAC STQDS62PD6PCLYBAB7LPYTG47WMBJP3FIJL55UHC3XFDPGERC3UQC ND3T5LCZATC63EVQ6SLI7XXMSUL7XICJDNLH3UCYUDEFWTA3N5MQC PSCYVKJ7DGXAL3V5U4O6AJTRV6Q3N3SHQWAZ73VIPRTE4W64F2XAC 4VV5V2ZLRNS6TDMQR7ZAE5INGFZAGNLJ5GXFMMX5JJWZEJSLFS7QC SH6NU4H5TG4O7CRXRHZ7MDHABZLWWXQ77NJDBHI7KCVHXHQYK46QC SQV4OUWNCYWQTAVHXNK4AENJAEOU2YZOJNJTRWVDZZHOEG6OVAFAC 7G4KWTOOBRLHOZZGFGAXGTUCDF3FGSZOXVHUZZ3V2KVWYSFE7EKAC EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC KEANRIMF5CGFVZ2XJYNFPOAKLXOSOJUOVA73IWBWOG576265ERHAC 3VWSZUGYL36SO5AOZRASGK3VHFCFZUGGCGRT3R7BZB36IZPN7OSQC 36SHRKVELEOW7PUDHUS2ONWI6OEHUTP6NBFGOT4GR6ZS3QZRTK5AC CNTJFUFA4A3L53QEITFZEWL4R4AXOXP4L3K4X5NSKFHBAFSREIQAC LAMIVDKY7LO5ONX5Z273ZCCEA5UBENOJD5VWNE4AK2EXGFED6BFQC 2GV6OW7P54FXZ5OD2NUMX7MLXH424LYAFMOAUQ2UGSOLKLYDBJGAC SXQ32Z7ZILMUYSDTK3WE6OOEBYZURCJIUDHT3PXVPV44CBZTPGJQC L2BH25YQXSIQ7B66SXO7Q3IWUFVX7HTERRJZ5ZJJZS54ZETVFP6AC AYYQVALBAAKFK5U52WGHWE2N7LCVZM3BGRADPVJQWOFLS2TXK6QAC YOZHWGKGPWZGHQYNMMBHNGDO2UEVIHPOR6UF3SEZPIYWVMBGWBOAC JJCHVUDSWKDHVKOYATOUV7RLXAMVMTL6FFFVR7OBW57OCD7MW3PQC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC 542UIZKI65UDRNEMGFFDBWYD5XC7AYLTZ3JZQRR2GHYJALD3YY6QC DGB7DKTR6OEQEMOOF3MAHDT4PAPKZ54Y33MWYVD7XIOESPFAXHQQC QCUMH3C7GXV7ZW444WT5SFAXQOJKJSE2YCQCEHMRYXCWF4QI7UMAC XI7U6RL6MFTH6SZQMLO4XFWGXGIFJBCRT6ZFCJFR2B2MGRSKDDCAC OXHOOJE4XEQKGI3JKURNSITG6CRQFAOFQ2EKKG6M5DCLN7LS4GUAC FRLPNEJJAGFWOJ5KJAE4PUQZN3EA4UAFKKUNN2UL5CRWKJRLMMJQC PBRFKFYILME3A2YLLVGRWJ2C7PCE2GONSINX65P4EG22ZGCW6JWAC YMC3RKF4Z7DOHZNGG7INC343SXCTWOPK7ISD42I3WA3AZZNVBGIAC TM35IHKZZNBCMR3ERBS4EYHGUK5IVCPUT2JUITMT74AYAIUZSYFQC RX6575DZOHRUXQUZH34YZGPZJF4STUPLBQDIVTINA2L6LVCKRIGQC ZVJPCEGKZ3MMRTTN563KQOSA7LFVFMMUDVARW2W5YQG6XZB6U7UAC CYAVI4PYWMMKTPYT5N2B3MI4OSHZFLPKOZFSLFJUXRYAACYXWW3AC 67AF33NTJG4WEAIFQX4R5XZTC5XZ5IBVHSFLYTGOXQJIXCZVXKDQC V4C7Y3VML7H7IXW5IZYL4ONSBUYDEU6RSRCDCOAZD7SZ4ZC2ONPAC WSENSWVHRNAW2NZO3HQLRV3HJKULA4JQHKM65M2NINZSD6NRQAMAC DGHHGJ6RCXFF3I53K2DI2FDB3UW2SUZAWWAQ7T6YW6374WOQASUQC BFYHDL4EHSPKKC6EPKDRPESHYAA2WFKC6RXQIRRTSSTF3Z2QPVCAC RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC 3SBEV2BQOK6TVP7CJHXL7QHQDLYWJXVA6JCV4YCZT6LYXE3IDPHAC 4PAWVDF5IXOGPB5OLYXGTLUNAEZI3KNSW7AKJKQAIOLQGQBFAFBAC Z5Q3G3R4UCP236KXS4MW4LVRIM3LTEKG4J4XVMGO7ISA3XUWXYMQC CE6FLTWU5PYFBSGVTIJXQXRMHOIHQ3VJCKHQVIMUUAIFHQ73X7NAC 3GLHLYH34NUBL2C5HSECKNVAO4ZFAAYXCW3Q5VZ2PXDDZ4SDD7LQC MDAJYB6STTZPNHRQ2X66MMMSONMKXTESLHJSFPGN7H3D3TOVBAVAC 3UHMSNL7FEGVWYDX6AAJD2XQUQQ3HJMMTDR66IORZPYP5MJ2L7AQC 4HLF6Q3OBOOHCCJ76L2BXVIYI6EMJ2G7O4XXZPFTLFP6BQGSUZNAC UH3CJQMQ3NPICXD34NTCTUZJWOCEF4P5XEGXFLLNDDFLZK7QPUBQC HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC TPPJRQ2NTCV3GI2VRHEXQJREDERPJODCJWUG5WCOQGN4REPPPAMAC SPOCLROO64OKT2F6SGUJNAQXH2XZWCK3LE7IRCDQCRYPU6Q6SAFQC DF5LOTJFSXOT7UBDHLBDLGA22OY4L7ZF6CVFP6H3KL4N5CHB5C5QC 2BTN774TDEFKS7L23YNEDQJSLSUWWKXPC5GA73ZGKLCKDHVEWSJAC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC Z3RI4XAN7J2GUABAQ5G6YIOQYMBOAEQFFGRBWHMUEB2A2QYXO5MQC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC IQGGFC563RBS7GDOACKCLXK752EE5RC3T6G5L6H446SXTMSA7T2AC 4FQAKUKUO6PCAZ3N4HUR5XL6E4VA5UQUZ3AEDGRBLVY7W2LMWI7QC 6TEISZD7HYSSL24EOKIBNURU66KGSQX7B7SNAHBP4DQSAOTGH2MQC NCHTJYDWTFLBWRQ3NS47O4ZAPT6RN7P2GNUT7G2PPVNURCLCWW6AC YHSVOROKPYS33Y4RYZRVZTE3G5LXOFX52HEDNLV6HIXOJYNOKH3QC 5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC VIFZ6DO6GWJGYMXJZKFZ2JYNPHNE74H3OFAOCPISQG7M7A4LCOHAC YF2GZWXNV6NVFFEBEOYS67JQJQK2IUS5BZMGJW3XQPYIJYHQJCEQC 5OVWAD2MGK2NT6Q546KW7HZHELVDBBRC2CQX6VZMZF2YVRC7CPVAC #include "AppHdr.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef USE_X11 //Sys dep#include <X11/Xlib.h>#include <X11/X.h>#include <X11/Xutil.h>#include <X11/Xlocale.h>#include <X11/keysym.h>#include <X11/keysymdef.h>#include <X11/Xmd.h>#endif#include "cio.h"#include "enum.h"#include "externs.h"#include "guic.h"#include "libutil.h"/** Tile related stuff*/#ifdef USE_TILE#include "tiles.h"static Display *display=NULL;static int screen;static int x11_keypress(XKeyEvent *xev);static void x11_check_exposure(XEvent *xev);extern WinClass *win_main;void GetNextEvent(int *etype, int *key, bool *shift, bool *ctrl,{XEvent xev;{XNextEvent(display, &xev);{int button = xev.xbutton.button;*shift = (xev.xkey.state & ShiftMask) ? true : false;*ctrl = (xev.xkey.state & ControlMask) ? true : false;*x1 = xev.xbutton.x;*y1 = xev.xbutton.y;*key = button;}{*x1 = xev.xbutton.x;*y1 = xev.xbutton.y;}{int button = xev.xbutton.button;*x1 = xev.xbutton.x;*y1 = xev.xbutton.y;*key = button;break;}char *my_getenv(const char *envname, const char *def){const char *result = getenv(envname);return (char *)result;}int my_getenv_int(const char *envname, int def){const char *rstr = getenv(envname);return atoi(rstr);}extern WinClass *win_main;extern TextRegionClass *region_tip;void update_tip_text(const char *tip){return;{{// try to remove inscriptions{*ins = 0;}else{// try to remove state, e.g. "(worn)"{*state = 0;}else{// if nothing else...}}}}}void TileDrawDungeonAux(){}#endif /* USE_TILE *//* X11 */int sx, sy, ex, ey;sx = xev->xexpose.x;sy = xev->xexpose.y;win_main->redraw(sx,sy,ex,ey);}/* X11 */// This routine is taken from Angband main-x11.cint x11_keypress(XKeyEvent *xev){#define IsSpecialKey(keysym) \((unsigned)(keysym) >= 0xFF00){};int dir, base;int n;bool mc, ms, ma;unsigned int ks1;XKeyEvent *ev = (XKeyEvent*)(xev);KeySym ks;char buf[256];n = XLookupString(ev, buf, 125, &ks, NULL);buf[n] = '\0';if (IsModifierKey(ks)) return 0;/* Extract "modifier flags" */mc = (ev->state & ControlMask) ? true : false;/* Normal keys */if (n && !IsSpecialKey(ks)){buf[n] = 0;}/* Hack -- convert into an unsigned int */ks1 = (uint)(ks);/* Handle a few standard keys (bypass modifiers) XXX XXX XXX */base = dir = 0;switch (ks1)//Handle keypad firstif (dir != 0){}if (base != 0){}//Hack Special key{}return 0;}void libgui_init_sys(){GuicInit(&display, &screen);}void libgui_shutdown_sys(){GuicDeinit();}void update_screen(){XFlush(display);}int kbhit(){XEvent xev;{XPutBackEvent(display, &xev);return 1;}return 0;}void delay( unsigned long time ){usleep( time * 1000 );}/* Convert value to string */int itoa(int value, char *strptr, int radix){unsigned int bitmask = 32768;int ctr = 0;int startflag = 0;if (radix == 10){sprintf(strptr, "%i", value);}{while (bitmask){if (value & bitmask){startflag = 1;sprintf(strptr + ctr, "1");}{}bitmask = bitmask >> 1;if (startflag)ctr++;}if (!startflag) /* Special case if value == 0 */sprintf((strptr + ctr++), "0");strptr[ctr] = (char) NULL;}return (0); /* Me? Fail? Nah. */}// Convert string to lowercase.char *strlwr(char *str){unsigned int i;for (i = 0; i < strlen(str); i++)str[i] = tolower(str[i]);return (str);}int stricmp( const char *str1, const char *str2 ){return (strcmp(str1, str2));}sprintf(strptr + ctr, "0");else if (startflag)else if (radix == 2) /* int to "binary string" */if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &xev))base = 512 + ks1 - 0xff00;if (ms) base |= 1024;if (mc) base |= 2048;if (ma) base |= 4096;return base;if (ks1 >=0xff00)if (ms) base |= 1024;if (mc) base |= 2048;if (ma) base |= 4096;return base;if (ms) result += CK_SHIFT_UP - CK_UP;if (mc) result += CK_CTRL_UP - CK_UP;return result;int result = ck_table[dir-1];// Keypadcase XK_KP_1:case XK_KP_End:dir = 1;break;case XK_KP_2:case XK_KP_Down:dir = 2;break;case XK_KP_3:case XK_KP_Page_Down:dir = 3;break;case XK_KP_6:case XK_KP_Right:dir = 6;break;case XK_KP_9:case XK_KP_Page_Up:dir = 9;break;case XK_KP_8:case XK_KP_Up:dir = 8;break;case XK_KP_7:case XK_KP_Home:dir = 7;break;case XK_KP_4:case XK_KP_Left:dir = 4;break;case XK_KP_5:dir = 5;break;}// for menuscase XK_Down:return CK_DOWN;case XK_Up:return CK_UP;case XK_Left:return CK_LEFT;case XK_Right:return CK_RIGHT;{case XK_Escape:base = 0x1b;break;case XK_Return:base = '\r';break;case XK_Tab:base = '\t';break;case XK_Delete:case XK_BackSpace:base = '\010';break;/* Alt + ? */return 2048|buf[0];if (!ma)return buf[0];// Hack Ctrl + [0-9] etc.if (mc && ((ks >= '0' && ks <= '9') || buf[0] >= ' '))return 1024 | ks;ms = (ev->state & ShiftMask) ? true : false;ma = (ev->state & Mod1Mask) ? true : false;CK_END, CK_DOWN, CK_PGDN,CK_LEFT, CK_INSERT, CK_RIGHT,CK_HOME, CK_UP, CK_PGUPconst unsigned int ck_table[9] =if (xev->xany.window != win_main->win)return;ey = xev->xexpose.y + (xev->xexpose.height) - 1;ex = xev->xexpose.x + (xev->xexpose.width) - 1;void x11_check_exposure(XEvent *xev){if (is_main_screen){region_tip->addstr(this_tip);region_tip->make_active();}else{ASSERT(i == 0);textattr(WHITE);cprintf("%s", this_tip);clear_to_end_of_line();}cgotoxy(1, get_number_of_lines() + 1);region_tip->cgotoxy(1, 1 + i);this_tip[width-1] = '.';this_tip[width-2] = '.';this_tip[width] = 0;char *state = strchr(this_tip, '(');if (state && state[-1] == ' ')state--;if (state && (state - this_tip <= (int)width))char *ins = strchr(this_tip, '{');if (ins && ins[-1] == ' ')ins--;if (ins && (ins - this_tip <= (int)width))char *this_tip = next_tip;// find end of linechar *pc = strchr(next_tip, '\n');if (pc){*pc = 0;next_tip = pc + 1;}elsenext_tip = 0;if (strlen(this_tip) > width)char *next_tip = new_tip;for (unsigned int i = 0; next_tip && i < height; i++)if (is_main_screen)region_tip->clear();const bool is_main_screen = (win_main->active_layer == 0);const unsigned int height = is_main_screen ? region_tip->my : 1;const unsigned int width = is_main_screen ? region_tip->mx: region_crt->mx;strncpy(new_tip, tip, tip_size);strncpy(old_tip, new_tip, tip_size);if (strncmp(old_tip, tip, tip_size) == 0)const unsigned int tip_size = 512;static char old_tip[tip_size];char new_tip[tip_size];extern TextRegionClass *region_crt;if (!rstr)return def;if (!result)result = def;}}if (button == 3)button = 2;else if (button == 2)button = 3;*etype = EV_UNBUTTON;else if (xev.type == ButtonRelease)break;}else if (xev.type == LeaveNotify){*etype = EV_MOVE;*x1 = -100;*y1 = -100;break;*etype = EV_MOVE;else if (xev.type == MotionNotify || xev.type == EnterNotify)break;if (button == 3)button = 2;else if (button == 2)button = 3;*etype = EV_KEYIN;*key = x11_keypress(&(xev.xkey));break;}else if (xev.type == Expose){x11_check_exposure(&xev);}else if (xev.type == ConfigureNotify){win_main->ox = xev.xconfigure.x;win_main->oy = xev.xconfigure.y;break;}else if (xev.type == ButtonPress){*etype = EV_BUTTON;if (xev.type == KeyPress)while (true)int *x1, int *y1, int *x2, int *y2)/** File: guic-win.cc* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/
#include <windows.h>#include <windowsx.h>#include <commdlg.h>#include <commctrl.h>// GDT_NONE in commctrl.h conflicts with enum.h#ifdef GDT_NONE#undef GDT_NONE#endif#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <memory.h>#include <tchar.h>#include "AppHdr.h"#include "cio.h"#include "externs.h"#include "guic.h"#include "itemprop.h"#include "state.h"#include "tiles.h"extern int old_main(int argc, char *argv[]);extern WinClass *win_main;extern TileRegionClass *region_tile;extern img_type TileImg;extern BYTE pix_transparent;typedef struct ev_data{int type;int key;int x1, y1;bool sh, ct;}ev_data;#define EV_MAX 1024struct ev_data ev_cue[EV_MAX];static int ev_head = 0;static int ev_tail = 0;void ev_push(struct ev_data *e);static bool skip_key = false;// Tip textstatic TOOLINFO tiTip;static HWND hTool;static HWND pWin;#ifdef USE_TILE#define PAL_STD 0 //standard palette#define PAL_BER 1 //berserk palette#define PAL_SHA 2 //shadow palettestatic int palette = PAL_STD;LPBYTE lpPalettes[3] ;#endif#define DF_TOOLTIP_WIDTH 300ATOM MyRegisterClass( HINSTANCE hInstance );BOOL InitInstance( HINSTANCE, int );LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );bool libgui_init_sys();void libgui_shutdown_sys();void update_tip_text(const char *tip);void GetNextEvent(int *etype, int *key, bool *shift, bool *ctrl,void TileInitWin();void delay(unsigned long ms);int kbhit();/***************************/void TileInitWin(){int i;TileImg->pDib->bmiColors[pix_transparent].rgbRed = 0;TileImg->pDib->bmiColors[pix_transparent].rgbGreen = 0;TileImg->pDib->bmiColors[pix_transparent].rgbBlue = 0;RegionClass::set_std_palette(&TileImg->pDib->bmiColors[0]);lpPalettes[0] = (LPBYTE) (&TileImg->pDib->bmiColors[0]);for (i = 0; i < 256; i++){chcol = (TileImg->pDib->bmiColors[i].rgbRed * 30ptr[2] = (BYTE)chcol;ptr[0] = (BYTE)( (chcol +1)/6 );ptr[1] = (BYTE)( (chcol +1)/6 );ptr[2] = ptr[0] = ptr[1] = (BYTE)chcol;}}void update_tip_text(const char *tip){#define MAXTIP 512static char oldtip[MAXTIP+1];strncpy(oldtip, tip, MAXTIP);tiTip.lpszText = (char *)tip;SendMessage(hTool, TTM_UPDATETIPTEXT, 0, (LPARAM)&tiTip);}bool libgui_init_sys( ){}void libgui_shutdown_sys(){DestroyWindow( pWin );}void GetNextEvent(int *etype, int *key, bool *sh, bool *ct,{MSG msg;{TranslateMessage( &msg );DispatchMessage( &msg );}struct ev_data *e = &ev_cue[ev_head];ev_head++;ev_head = 0;*etype = e->type;*key = e->key;*sh = e->sh;*ct = e->ct;*x1 = e->x1;*y1 = e->y1;}void ev_push(struct ev_data *e){ev_cue[ev_tail] = *e;ev_tail++;ev_tail = 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,{MSG msg;MyRegisterClass( hInstance );GuicInit(hInstance, nCmdShow);return msg.wParam;}ATOM MyRegisterClass( HINSTANCE hInstance ){WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX);wcex.style = CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc = (WNDPROC)WndProc;wcex.cbClsExtra = 0;wcex.cbWndExtra = 0;wcex.hInstance = hInstance;wcex.hIcon = LoadIcon(hInstance, TEXT("CRAWL_ICON"));wcex.hCursor = LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);wcex.lpszMenuName = "CRAWL";wcex.lpszClassName = "CrawlList";wcex.hIconSm = NULL;//LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);return RegisterClassEx( &wcex );}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;struct ev_data ev;static int clix = 0;static int cliy = 0;// For keypad{};switch( message ){case WM_CREATE:{pWin = hWnd;InitCommonControls();hTool = CreateWindowEx( 0 , TOOLTIPS_CLASS ,NULL , TTS_ALWAYSTIP ,CW_USEDEFAULT , CW_USEDEFAULT ,CW_USEDEFAULT , CW_USEDEFAULT ,hWnd , NULL , ((LPCREATESTRUCT)(lParam))->hInstance ,NULL);tiTip.hwnd = hWnd;tiTip.lpszText = (char *)SendMessage(hTool, TTM_ADDTOOL , 0 , (LPARAM)&tiTip);return 0;}case WM_RBUTTONDOWN:case WM_LBUTTONDOWN:case WM_MBUTTONDOWN:{ev.x1 = LOWORD(lParam);ev.y1 = HIWORD(lParam);ev.key = 1;if (message == WM_RBUTTONDOWN) ev.key = 2;if (message == WM_MBUTTONDOWN) ev.key = 3;return 0;}case WM_RBUTTONUP:ev.x1 = LOWORD(lParam);ev.y1 = HIWORD(lParam);ev.key = 1;if (message == WM_RBUTTONUP) ev.key = 2;if (message == WM_MBUTTONUP) ev.key = 3;return 0;case WM_MOUSEWHEEL:{return 0;}case WM_MOUSEMOVE:{ev.x1 = LOWORD(lParam);ev.y1 = HIWORD(lParam);return 0;}case WM_KEYDOWN:{int result = 0;{switch(ch){case VK_LEFT: dir = 4; break;case VK_RIGHT: dir = 6; break;case VK_UP: dir = 8; break;case VK_DOWN: dir = 2; break;case VK_HOME: dir = 7; break;case VK_PRIOR: dir = 9; break;case VK_NEXT: dir = 3; break;case VK_END: dir = 1; break;case VK_CLEAR: dir = 5; break;}if (dir != 0){if (fc)if (fs)ev.key = ch;return 0;}case WM_CHAR:{ev.key = (int)wParam;return 0;}case WM_PAINT:{hdc = BeginPaint(hWnd, &ps);win_main->redraw();EndPaint(hWnd, &ps);return 0;}case WM_COMMAND:{wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);switch( wmId ){default:return DefWindowProc( hWnd, message, wParam, lParam );}return 0;}case WM_CLOSE:{if (crawl_state.need_save)save_game(true);}break;case WM_DESTROY:{PostQuitMessage( 0 );exit(0);break;}default:return DefWindowProc( hWnd, message, wParam, lParam );}return 0;}#ifdef USE_TILEdib_pack *pBuf = region_tile->backbuf;if (new_palette != palette){SetDIBColorTable(pBuf->hDC, 0, 256, (RGBQUAD *)lpPalettes[palette]);}}#endifbool windows_change_font(char *font_name, int *font_size, bool dos){CHOOSEFONT cf;memset(&cf, 0, sizeof(cf));cf.lStructSize = sizeof(cf);cf.iPointSize = *font_size;cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_NOVERTFONTSLOGFONT lf;strcpy(lf.lfFaceName, font_name);cf.lpLogFont = &lf;if (ChooseFont(&cf)){*font_size = (cf.iPointSize / 10);strcpy(font_name, lf.lfFaceName);}}void windows_get_winpos(int *x, int *y){WINDOWPLACEMENT wndpl;// set lengthwndpl.length = sizeof( WINDOWPLACEMENT );{*x = wndpl.rcNormalPosition.top;*y = wndpl.rcNormalPosition.left;}}void delay(unsigned long ms){Sleep((DWORD)ms);}int kbhit(){MSG msg;if (PeekMessage(&msg, NULL, WM_CHAR, WM_CHAR, PM_NOREMOVE)return 1;elsereturn 0;}void update_screen(){}}|| PeekMessage(&msg, NULL, WM_KEYDOWN, WM_KEYDOWN, PM_NOREMOVE)){if (GetWindowPlacement( win_main->hWnd, &wndpl ) != 0)return (false);return (true);lf.lfHeight = 16;lf.lfWidth = 0;lf.lfEscapement = 0;lf.lfOrientation = lf.lfEscapement;lf.lfWeight = FW_NORMAL;lf.lfItalic = FALSE;lf.lfUnderline = FALSE;lf.lfStrikeOut = FALSE;lf.lfOutPrecision = OUT_DEFAULT_PRECIS;lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;lf.lfQuality = DEFAULT_QUALITY;lf.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;lf.lfCharSet = (dos)? OEM_CHARSET:ANSI_CHARSET;| CF_INITTOLOGFONTSTRUCT | CF_LIMITSIZE | CF_FORCEFONTEXIST;cf.nSizeMin = 8;cf.nSizeMax = 24;palette = new_palette;int new_palette = PAL_STD; // standardif (you.duration[DUR_BERSERKER])new_palette = PAL_BER;// XXX: is this supposed to override Berserk?if (you.special_wield == SPWLD_SHADOW)new_palette = PAL_SHA;void TileDrawDungeonAux(){libgui_shutdown();if (mouse_get_mode() == MOUSE_MODE_COMMAND|| !crawl_state.need_save )// XXX: Isn't that always the case?case WM_MOVE:{clix = LOWORD(lParam);cliy = HIWORD(lParam);return 0;}ev.type = EV_KEYIN;ev_push(&ev);if (skip_key){skip_key = false;return 0;}return 0;if (result){if (fs) result |= 512;if (fc) result |= 1024;if (fa) result |= 2048;ev.key = result;ev.type = EV_KEYIN;ev_push(&ev);}}{}result = 300 + ch;else if (ch >= VK_PAUSE&& (ch < VK_CAPITAL || ch > VK_SPACE)&& ch != VK_PROCESSKEY&& ch != VK_NUMLOCK&& (ch < VK_LSHIFT || ch > VK_RMENU)&& (ch < 0x30 || ch > 0x39)&& (ch < 0x41 || ch > 0x5a)&& (ch < 0xa6 || ch > 0xe4))ev.type = EV_KEYIN;ev_push(&ev);if (fa)ch |= 2048;ch += CK_SHIFT_UP - CK_UP;ch += CK_CTRL_UP - CK_UP;ch = ck_table[dir-1];}if (ch >= VK_NUMPAD1 && ch <= VK_NUMPAD9){skip_key = true;dir = ch - VK_NUMPAD0;}else if (VK_PRIOR <= ch && ch <= VK_DOWN || ch == VK_CLEAR)int dir = 0;bool fs = ((GetKeyState(VK_SHIFT) & 0x80) != 0)? true : false;bool fc = ((GetKeyState(VK_CONTROL)& 0x80) != 0)? true : false;bool fa = ((GetKeyState(VK_MENU) & 0x80) != 0)? true : false;int ch = (int) wParam;ev_push(&ev);ev.type = EV_MOVE;int z = (short)HIWORD(wParam);ev.x1 = LOWORD(lParam) - clix;ev.y1 = HIWORD(lParam) - cliy;ev.type = EV_BUTTON;ev.sh = ((GetKeyState(VK_SHIFT) & 0x80) != 0) ? true : false;ev.ct = ((GetKeyState(VK_CONTROL) & 0x80) != 0) ? true : false;ev.key = (z > 0) ? 4 : 5;ev_push(&ev);}ev_push(&ev);{ev.type = EV_UNBUTTON;ev_push(&ev);ev.sh = ((GetKeyState(VK_SHIFT) & 0x80) != 0)? true : false;ev.ct = ((GetKeyState(VK_CONTROL) & 0x80) != 0)? true : false;ev.type = EV_BUTTON;// Allow line wrapSendMessage(hTool, TTM_SETMAXTIPWIDTH, 0, DF_TOOLTIP_WIDTH);"This text will tell you" EOL" what you are pointing";tiTip.cbSize = sizeof (TOOLINFO);tiTip.uFlags = TTF_SUBCLASS;GetClientRect(hWnd , &tiTip.rect);// Example taken from// http://black.sakura.ne.jp/~third/system/winapi/common10.htmlCK_END, CK_DOWN, CK_PGDN,CK_LEFT, CK_INSERT, CK_RIGHT,CK_HOME, CK_UP, CK_PGUPconst unsigned char ck_table[9] =// Redirect output to the consoleAttachConsole(ATTACH_PARENT_PROCESS);freopen("CONOUT$", "wb", stdout);freopen("CONOUT$", "wb", stderr);// I'll be damned if I have to parse lpCmdLine myself...int argc;LPWSTR *wargv = CommandLineToArgvW(GetCommandLineW(), &argc);char *ptr = args;for (int i = 0; i < argc; i++){wsprintfA(ptr, "%S", wargv[i]);argv[i] = ptr;ptr += strlen(argv[i]) + 1;}ASSERT(ptr <= args + args_len);old_main(argc, argv);delete args;delete argv;FreeConsole();char **argv = new char*[argc];int args_len = wcslen(GetCommandLineW()) + argc;char *args = new char[args_len];LPSTR lpCmdLine, int nCmdShow )if (ev_tail == EV_MAX)if (ev_head == EV_MAX)if (ev_tail != ev_head)break;while ( GetMessage(&msg, NULL, 0, 0) )int *x1, int *y1, int *x2, int *y2)GlobalFree(lpPalettes[1]);GlobalFree(lpPalettes[2]);return (true);if (strncmp(oldtip, tip, MAXTIP) == 0)return;ptr = lpPalettes[2] + i * sizeof(RGBQUAD);+ TileImg->pDib->bmiColors[i].rgbGreen * 59+ TileImg->pDib->bmiColors[i].rgbBlue * 11) / 100;LPBYTE ptr = lpPalettes[1] + i * sizeof(RGBQUAD);lpPalettes[1] = (LPBYTE)GlobalAlloc(GPTR, 256 * sizeof(RGBQUAD) );lpPalettes[2] = (LPBYTE)GlobalAlloc(GPTR, 256 * sizeof(RGBQUAD) );WORD chcol;int *x1, int *y1, int *x2, int *y2);#include "files.h"#include "debug.h"#include <fcntl.h>/** File: guic-win.cc* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/#define _WIN32_WINNT 0x0501
#ifdef USE_X11#include <X11/Xlib.h>#include <X11/X.h>bool GuicInit(Display **d, int *s);void GuicDeinit();#elif defined(WIN32TILES)#include <windows.h>#include <commdlg.h>bool GuicInit(HINSTANCE h, int nCmdShow);void GuicDeinit();#elif defined(SOME_OS)#include <some-headers.h>bool GuicInit(some args);#endif#include <vector>/** Internal Image types*/#ifdef USE_X11/*********** X11 ********/typedef XImage *img_type;#define ImgWidth(img) (img->width)#define ImgHeight(img) (img->height)#elif defined(WIN32TILES)/********** Windows *****/// struct for DIB infotypedef struct dib_pack{} dib_pack;typedef dib_pack *img_type;#define ImgWidth(img) (img->Width)#define ImgHeight(img) (img->Height)#elif defined(SOME_OS)typedef sometype *img_type;#define ImgWidth(img) (img->x)#define ImgHeight(img) (img->y)#endif// Image overlay/copy between internal images,// implemented in winclass-*.ccvoid ImgCopy(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, int copy);// hilight rim color #010101 to magentavoid ImgCopyH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, int copy);// maskout by char array maskvoid ImgCopyMasked(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask);// maskout+hilightvoid ImgCopyMaskedH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask);// create internal buffer (not assosiated to any window)img_type ImgCreateSimple(int wx, int wy);// create it from fileimg_type ImgLoadFile(const char *name);// destroyvoid ImgDestroy(img_type img);// clear by transparent colorvoid ImgClear(img_type img);// if it is pix_transparent #476c6cbool ImgIsTransparentAt(img_type img, int x, int y);void ImgSetTransparentPix(img_type img);/** Windows and internal regions (text, dungeon, map, etc)*/class WinClass{public:int ox; //Offset x in dotsint oy; //Offset y in dotsint wx; //width in dotsint wy; //height in dotsstd::vector<class RegionClass *> regions;std::vector<int> layers;int active_layer;// Pointer to the window#ifdef USE_X11Window win;#elif defined(WIN32TILES)HWND hWnd;#elif defined(SOME_OS)somewindowtype win;#endifWinClass();void SysInit();void SysDeinit();~WinClass();// fillout with black: Sys depvoid clear();// create: Sys dep#ifdef USE_X11void create(char *name);#elif defined(WIN32TILES)BOOL create(const char *name);#elif defined(SOME_OS)void create(some args);#endifvoid resize(int wx, int wy);void resize();void move(int ox, int oy);void move();// place Regions inside itint pflag,int margin_bottom = 0, int margin_right = 0);int x, int y,int margin_bottom = 0, int margin_right = 0);// fillout a rectanglevoid fillrect(int left, int right, int top, int bottom, int color);// redraw for exposure, etcvoid redraw(int x1, int y1, int x2, int y2);void redraw();};class RegionClass{public:WinClass *win;int layer;// Geometry// <-----------------wx----------------------->// sx ox ex// |margin| text/tile area |margin|int ox; //Offset x in dotsint oy; //Offset y in dotsint dx; //unit widthint dy; //unit heightint mx; //window width in dxint my; //window height in dyint wx; //width in dots = dx*mx + marginsint wy; //height in dots = dy*my + marginsint sx; //Left edge posint sy; //Top edge posint ex; //right edge posint ey; //bottom edge posbool flag;// use or noint id; // for general purpose// pointer to internal backup image buffer// used for redraw and supplessing flickerimg_type backbuf;#ifdef WIN32TILESstatic void set_std_palette(RGBQUAD *pPal);static RGBQUAD std_palette[256];void init_backbuf(RGBQUAD *pPal = NULL, int ncol = 0);bool dos_char;#elsevoid init_backbuf();#endifvoid resize_backbuf();// font-relatedint fx; // font height and width (can differ from dx, dy)int fy;#ifdef USE_X11int asc; //font ascent#ifdef JPXFontSet font; //fontset#elseXFontStruct *font;#endifvoid init_font(const char *name);#elif defined(WIN32TILES)HFONT font;void init_font(const char *name, int height);void change_font(const char *name, int height);#elif defined(SOME_OS)sometype font;void init_font(some args);#endifbool font_copied;void copy_font(RegionClass *r);// init/deinitRegionClass();virtual ~RegionClass();// system-dependent init/deinitvoid SysInit();void SysDeinit();// Sys indepbool is_active();void make_active();//Sys indep// convert mouse point into logical positionvirtual bool mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy);virtual bool convert_redraw_rect(int x1, int y1, int x2, int y2,int *rx1, int *ry1, int *rx2, int *ry2);virtual void redraw(int x1, int y1, int x2, int y2);virtual void redraw();void sys_flush();virtual void fillrect(int left, int right, int top, int bottom, int color);virtual void framerect(int left, int right, int top, int bottom, int color);virtual void clear();};class TextRegionClass :public RegionClass{public:// init/deinitTextRegionClass(int x, int y , int cx, int cy);~TextRegionClass();// os dependent init/deinitvoid SysInit(int x, int y, int cx, int cy);void SysDeinit();// where now printing? what color?static int print_x;static int print_y;static int text_col;// which region now printing?static class TextRegionClass *text_mode;// display cursor? where is the cursor now?static int cursor_flag;static class TextRegionClass *cursor_region;static int cursor_x;static int cursor_y;// class methodsstatic int wherex();static int wherey();//static int get_number_of_lines(void);static void _setcursortype(int curstype);static void textbackground(int bg);static void textcolor(int col);// Object's methodvoid clear_to_end_of_line(void);void clear_to_end_of_screen(void);void putch(unsigned char chr);void writeWChar(unsigned char *ch);unsigned char *cbuf; //text backupunsigned char *abuf; //textcolor backupint cx_ofs; //cursor x offsetint cy_ofs; //cursor y offsetvoid addstr(char *buffer);void addstr_aux(char *buffer, int len);void adjust_region(int *x1, int *x2, int y);void scroll();//bool mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy);//Sys depvoid draw_string(int x, int y, unsigned char *buf, int len, int col);void draw_cursor(int x, int y, int width);void draw_cursor(int x, int y);void erase_cursor();void clear();void init_backbuf();void redraw(int x1, int y1, int x2, int y2);void resize(int x, int y);};class TileRegionClass :public RegionClass{public:bool force_redraw;void DrawPanel(int left, int top, int width, int height);void fillrect(int left, int right, int top, int bottom, int color);void framerect(int left, int right, int top, int bottom, int color);bool mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy);virtual bool convert_redraw_rect(int x1, int y1, int x2, int y2,int *rx1, int *ry1, int *rx2, int *ry2);void redraw(int x1, int y1, int x2, int y2);void redraw();void clear();//Sys depvoid resize(int x, int y, int dx, int dy);#ifdef WIN32TILESvoid init_backbuf(RGBQUAD *pPal = NULL);#elsevoid init_backbuf();#endifvoid resize_backbuf();TileRegionClass(int mx0, int my0, int dx0, int dy0);void SysInit(int mx0, int my0, int dx0, int dy0);void SysDeinit();~TileRegionClass();};{int mx2;int my2;int x_margin;int y_margin;unsigned char *mbuf;bool force_redraw;bool mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy);void redraw(int x1, int y1, int x2, int y2);void redraw();void clear();//Sys depvoid init_backbuf();void resize_backbuf();void resize(int mx0, int my0, int dx0, int dy0);void set_col(int col, int x, int y);int get_col(int x, int y);void SysInit(int x, int y, int o_x, int o_y);void SysDeinit();};#define PLACE_RIGHT 0#define PLACE_BOTTOM 1#define PLACE_FORCE 2// Graphics Colors#define PIX_BLACK 0#define PIX_BLUE 1#define PIX_GREEN 2#define PIX_CYAN 3#define PIX_RED 4#define PIX_MAGENTA 5#define PIX_BROWN 6#define PIX_LIGHTGREY 7#define PIX_DARKGREY 8#define PIX_LIGHTBLUE 9#define PIX_LIGHTGREEN 10#define PIX_LIGHTCYAN 11#define PIX_LIGHTRED 12#define PIX_LIGHTMAGENTA 13#define PIX_YELLOW 14#define PIX_WHITE 15#define MAX_TERM_COL 16#define MAP_BLACK 0#define MAP_DKGREY 1#define MAP_MDGREY 2#define MAP_LTGREY 3#define MAP_WHITE 4#define MAP_BLUE 5#define MAP_LTBLUE 6#define MAP_DKBLUE 7#define MAP_GREEN 8#define MAP_LTGREEN 9#define MAP_DKGREEN 10#define MAP_CYAN 11#define MAP_LTCYAN 12#define MAP_DKCYAN 13#define MAP_RED 14#define MAP_LTRED 15#define MAP_DKRED 16#define MAP_MAGENTA 17#define MAP_LTMAGENTA 18#define MAP_DKMAGENTA 19#define MAP_YELLOW 20#define MAP_LTYELLOW 21#define MAP_DKYELLOW 22#define MAP_BROWN 23#define MAX_MAP_COL 24extern const int term_colors[MAX_TERM_COL][3];extern const int map_colors[MAX_MAP_COL][3];protected:int old_mark_x;int old_mark_y;MapRegionClass(int x, int y, int o_x, int o_y, int marker_length);~MapRegionClass();void draw_data(unsigned char *buf, bool show_mark, int mark_x, int mark_y);int marker_length;public:class MapRegionClass : public RegionClassstatic void cgotoxy(int x, int y);void removeRegion(class RegionClass *r);int margin_top = 0, int margin_left = 0,void placeRegion(class RegionClass *r, int layer,int margin_top = 0, int margin_left = 0,void placeRegion(class RegionClass *r, int layer,class RegionClass *neighbor,LPBITMAPINFO pDib ;HBITMAP hDib ;HDC hDC ;LPBYTE pDibBits ;LPBYTE pDibZero ;int Width ;int Height ;/** File: guic-win.cc* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/
*/#include "guic.h"#ifdef WIN32TILES#else#define dos_char false;#endifint TextRegionClass::print_x;int TextRegionClass::print_y;TextRegionClass *TextRegionClass::text_mode = NULL;int TextRegionClass::text_col = 0;TextRegionClass *TextRegionClass::cursor_region= NULL;int TextRegionClass::cursor_flag = 0;int TextRegionClass::cursor_x;int TextRegionClass::cursor_y;// more logical color naming{{ 0, 0, 0}, // BLACK{128, 128, 128}, // DKGREY{160, 160, 160}, // MDGREY{192, 192, 192}, // LTGREY{255, 255, 255}, // WHITE{ 0, 64, 255}, // BLUE (actually cyan-blue){128, 128, 255}, // LTBLUE{ 0, 32, 128}, // DKBLUE (maybe too dark){ 0, 255, 0}, // GREEN{128, 255, 128}, // LTGREEN{ 0, 128, 0}, // DKGREEN{ 0, 255, 255}, // CYAN{ 64, 255, 255}, // LTCYAN (maybe too pale){ 0, 128, 128}, // DKCYAN{255, 0, 0}, // RED{255, 128, 128}, // LTRED (actually pink){128, 0, 0}, // DKRED{192, 0, 255}, // MAGENTA (actually blue-magenta){255, 128, 255}, // LTMAGENTA{ 96, 0, 128}, // DKMAGENTA{255, 255, 0}, // YELLOW{255, 255, 64}, // LTYELLOW (maybe too pale){128, 128, 0}, // DKYELLOW{165, 91, 0}, // BROWN};{{ 0, 0, 0}, // BLACK{ 0, 82, 255}, // BLUE{100, 185, 70}, // GREEN{ 0, 180, 180}, // CYAN{255, 48, 0}, // RED{238, 92, 238}, // MAGENTA{165, 91, 0}, // BROWN{162, 162, 162}, // LIGHTGREY{ 82, 82, 82}, // DARKGREY{ 82, 102, 255}, // LIGHTBLUE{ 82, 255, 82}, // LIGHTGREEN{ 82, 255, 255}, // LIGHTCYAN{255, 82, 82}, // LIGHTRED{255, 82, 255}, // LIGHTMAGENTA{255, 255, 82}, // YELLOW{255, 255, 255} // WHITE};WinClass::WinClass(){// Minimum;wx = 10;wy = 10;ox = 0;oy = 0;SysInit();}WinClass::~WinClass(){SysDeinit();regions.clear();layers.clear();}void WinClass::placeRegion(RegionClass *r, int layer0,int x, int y,int margin_top, int margin_left,int margin_bottom, int margin_right){if (r->win == NULL){regions.push_back(r);layers.push_back(layer0);}r->win = this;r->layer = layer0;r->flag = true;r->sx = x;r->sy = y;r->ox = r->sx + margin_left;r->oy = r->sy + margin_top;r->wx = r->dx * r->mx + margin_left + margin_right;r->wy = r->dy * r->my + margin_top + margin_bottom;r->ex = r->sx + r->wx;r->ey = r->sy + r->wy;if (r->ex > wx) wx = r->ex;if (r->ey > wy) wy = r->ey;}void WinClass::placeRegion(RegionClass *r, int layer0,RegionClass *neighbor, int pflag,int margin_top, int margin_left,int margin_bottom, int margin_right){int x = 0;int y = 0;if (neighbor!=NULL){sx0 = neighbor->sx;sy0 = neighbor->sy;ex0 = neighbor->ex;ey0 = neighbor->ey;}if (pflag == PLACE_RIGHT){x = ex0;y = sy0;}else{x = sx0;y = ey0;}placeRegion(r, layer0, x, y, margin_top, margin_left,margin_bottom, margin_right);}void WinClass::redraw(int x1, int y1, int x2, int y2){std::vector <RegionClass *>::iterator r;int cx1, cx2, cy1, cy2;{(*r)->redraw(cx1, cy1, cx2, cy2);}}void WinClass::redraw(){redraw(0, 0, wx-1, wy-1);}void WinClass::move(int ox0, int oy0){ox = ox0;oy = oy0;move(); // system dependent}void WinClass::resize(int wx0, int wy0){if (wx0>0) wx = wx0;if (wy0>0) wy = wy0;resize(); // system dependent}RegionClass::RegionClass(){flag = false;win = NULL;backbuf = NULL;SysInit();ox = oy = 0;dx = dy = 1;font_copied = false;id = 0;}RegionClass::~RegionClass(){SysDeinit();}void TextRegionClass::resize(int x, int y){int i;free(cbuf);free(abuf);cbuf = (unsigned char *)malloc(x*y);abuf = (unsigned char *)malloc(x*y);{}mx = x;my = y;}TextRegionClass::TextRegionClass(int x, int y, int cx, int cy){cbuf = NULL;abuf = NULL;resize(x, y);// Cursor Offsetcx_ofs = cx;cy_ofs = cy;SysInit(x, y, cx, cy);}TextRegionClass::~TextRegionClass(){SysDeinit();free(cbuf);free(abuf);}TileRegionClass::TileRegionClass(int mx0, int my0, int dx0, int dy0){// Unit sizedx = dx0;dy = dy0;mx = mx0;my = my0;force_redraw = false;SysInit(mx0, my0, dx0, dy0);}TileRegionClass::~TileRegionClass(){SysDeinit();}void TileRegionClass::resize(int mx0, int my0, int dx0, int dy0){if (mx0 != 0) mx = mx0;if (my0 != 0) my = my0;if (dx0 != 0) dx = dx0;if (dy0 != 0) dy = dy0;}{int i;mx2 = x;my2 = y;mx = mx2;my = my2;mbuf = (unsigned char *)malloc(mx2*my2);x_margin = o_x;y_margin = o_y;force_redraw = false;SysInit(x, y, o_x, o_y);}MapRegionClass::~MapRegionClass(){SysDeinit();free(mbuf);}void MapRegionClass::resize(int mx0, int my0, int dx0, int dy0){if (mx0 != 0) mx2 = mx0;if (my0 != 0) my2 = my0;if (dx0 != 0) dx = dx0;if (dy0 != 0) dy = dy0;if (mx0 != 0 || my0 != 0){int i;free(mbuf);mbuf = (unsigned char *)malloc(mx2*my2);}}/*------------------------------------------*/bool RegionClass::is_active(){if (win->active_layer == layer)}void RegionClass::make_active(){win->active_layer = layer;void RegionClass::redraw(int x1, int y1, int x2, int y2){}void RegionClass::redraw(){redraw(0, 0, mx-1, my-1);}void MapRegionClass::redraw(){redraw(0, 0, mx-1, my-1);}void TileRegionClass::redraw(){redraw(0, 0, mx*dx-1, my*dy-1);}void MapRegionClass::set_col(int col, int x, int y){mbuf[x + y * mx2] = col;}int MapRegionClass::get_col(int x, int y){return mbuf[x + y * mx2];}/*------------------------------------------*/int *rx1, int *ry1, int *rx2, int *ry2){int cx1 = x1-ox;int cy1 = y1-oy;int cx2 = x2-ox;int cy2 = y2-oy;cx1 /= dx;cy1 /= dy;cx2 /= dx;cy2 /= dy;*rx1 = cx1;*ry1 = cy1;*rx2 = cx2;*ry2 = cy2;}{int cx1 = x1-ox;int cy1 = y1-oy;int cx2 = x2-ox;int cy2 = y2-oy;int wwx = dx*mx;int wwy = dy*my;*rx1 = cx1;*ry1 = cy1;*rx2 = cx2;*ry2 = cy2;}bool RegionClass::mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy){int x = mouse_x - ox;int y = mouse_y - oy;x /= dx;y /= dy;*cx = x;*cy = y;}bool MapRegionClass::mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy){x /= dx;y /= dy;*cx = x;*cy = y;}bool TileRegionClass::mouse_pos(int mouse_x, int mouse_y, int *cx, int *cy){int x = mouse_x - ox;int y = mouse_y - oy;x /= dx;y /= dy;*cx = x;*cy = y;}void TextRegionClass::scroll(){int idx;return;{cbuf[idx] = cbuf[idx + mx];abuf[idx] = abuf[idx + mx];}{cbuf[idx] = ' ';abuf[idx] = 0;}redraw(0, 0, mx-1, my-1);}void TextRegionClass::adjust_region(int *x1, int *x2, int y){*x2 = *x2 + 1;}void TextRegionClass::addstr(char *buffer){int i,j;char buf2[1024];int len = strlen(buffer);{char c = buffer[i];{newline = true;i++;}buf2[j] = c;j++;{if (j-1 != 0)addstr_aux(buf2, j - 1); // draw itif (newline){print_x = cx_ofs;print_y++;}}}}void TextRegionClass::addstr_aux(char *buffer, int len){int i;int x = print_x - cx_ofs;int y = print_y - cy_ofs;int adrs = y * mx;int head = x;int tail = x + len - 1;adjust_region(&head, &tail, y);{}draw_string(head, y, &cbuf[adrs+head], tail-head, text_col);print_x += len;}void TextRegionClass::redraw(int x1, int y1, int x2, int y2){int x, y;{unsigned char *a = &abuf[y * mx];unsigned char *c = &cbuf[y * mx];int head = x1;int tail = x2;adjust_region(&head, &tail, y);int col = a[x];{int oldcol = col;col = -1;elsecol = a[x];if (oldcol != col){draw_string(head, y, &c[head], x-head, oldcol);head = x;}x++;}}draw_cursor(cursor_x, cursor_y);sys_flush();}void TextRegionClass::clear_to_end_of_line(){int i;int cx = print_x - cx_ofs;int cy = print_y - cy_ofs;int col = text_col;int adrs = cy * mx;}redraw(cx, cy, mx-1, cy);}void TextRegionClass::clear_to_end_of_screen(){int i;int cy = print_y - cy_ofs;int col = text_col;}redraw(0, cy, mx-1, my-1);}void TextRegionClass::putch(unsigned char ch){addstr_aux((char *)&ch, 1);}void TextRegionClass::writeWChar(unsigned char *ch){addstr_aux((char *)ch, 2);}void TextRegionClass::textcolor(int color){text_col = color;}void TextRegionClass::textbackground(int col){textcolor(col*16 + (text_col & 0xf));}{print_x = x-1;print_y = y-1;if (cursor_region != NULL && cursor_flag){cursor_region ->erase_cursor();cursor_region = NULL;}if (cursor_flag){text_mode->draw_cursor(print_x, print_y);cursor_x = print_x;cursor_y = print_y;cursor_region = text_mode;}}int TextRegionClass::wherex(){return print_x + 1;}int TextRegionClass::wherey(){return print_y + 1;}void TextRegionClass::_setcursortype(int curstype){cursor_flag = curstype;if (cursor_region != NULL)if (curstype){text_mode->draw_cursor(print_x, print_y);cursor_x = print_x;cursor_y = print_y;cursor_region = text_mode;}}cursor_region->erase_cursor();ASSERT(x >= 1);ASSERT(y >= 1);void TextRegionClass::cgotoxy(int x, int y)if (ch == 0)ch=32;for (i = cy*mx; i < mx*my; i++){cbuf[i] = ' ';abuf[i] = col;if (!flag)return;cbuf[adrs+i] = ' ';abuf[adrs+i] = col;ASSERT(adrs + mx - 1 < mx * my);for (i = cx; i < mx; i++){return;if (!flag)if (cursor_region == this && cursor_flag == 1)if (x == tail)while (x <= tail)x = head;for (y = y1; y <= y2; y++)return;if (!flag)cbuf[adrs+x+i] = buffer[i];abuf[adrs+x+i] = text_col;for (i = 0; i < len && x + i < mx; i++)return;if (!flag)if (cursor_flag)cgotoxy(print_x+1, print_y+1);scroll();if (print_y - cy_ofs == my)j = 0;if (c == 0)if (buffer[i+1] == '\n' || buffer[i+1] == '\r')c = 0;bool newline = false;if (c == '\n' || c == '\r')for (i = 0; i < len + 1; i++)j = 0;if (!flag)return;if (print_y > 0)print_y -= 1;if (cursor_y > 0)cursor_y -= 1;for (idx = mx*(my-1); idx < mx*my; idx++)for (idx = 0; idx < mx*(my-1); idx++)if (!flag)//// Text related//return (true);if (!is_active())return (false);if (x < 0 || y < 0)return (false);if (x >= dx * mx || y >= dy * my)return (false);return (true);if (x >= mx || y >= my)return (false);if (!is_active())return (false);int x = mouse_x - ox - x_margin;int y = mouse_y - oy - y_margin;if (x < 0 || y < 0)return (false);return (true);if (x >= mx || y >= my)return (false);if (!is_active())return (false);if ( x < 0 || y < 0 )return (false);return (true);if (cx2 >= wwx - 1)cx2 = wwx - 1;if (cy2 >= wwy - 1)cy2 = wwy - 1;if (cx1 < 0)cx1 = 0;if (cy1 < 0)cy1 = 0;if (cx2 < 0 || cy2 < 0 || cx1 >= wwx || cy1 >=wwy)return (false);bool TileRegionClass::convert_redraw_rect(int x1, int y1, int x2, int y2,int *rx1, int *ry1,int *rx2, int *ry2)return (true);if (cx2 >= mx - 1)cx2 = mx - 1;if (cy2 >= my - 1)cy2 = my - 1;if (cx1 < 0)cx1 = 0;if (cy1 < 0)cy1 = 0;if (cx2 < 0 || cy2 < 0 || cx1 >= dx * mx || cy1 >= dy * my)return (false);bool RegionClass::convert_redraw_rect(int x1, int y1, int x2, int y2,}if (!flag)return;return (true);elsereturn (false);if (!flag)return (false);for (i = 0; i < mx2*my2; i++)mbuf[i] = 0;marker_length = marker_len;old_mark_x = old_mark_y = 0;for (i = 0; i < mx2*my2; i++)mbuf[i] = 0;MapRegionClass::MapRegionClass(int x, int y, int o_x, int o_y, int marker_len)cbuf[i] = ' ';abuf[i] = 0;for (i = 0; i < x*y; i++)if (backbuf != NULL)ImgDestroy(backbuf);if (!(*r)->is_active())continue;if ( (*r)->convert_redraw_rect(x1, y1, x2, y2, &cx1, &cy1, &cx2, &cy2) )for (r = regions.begin();r != regions.end();r++)return;}}}void WinClass::removeRegion(RegionClass *r){for (unsigned int i = 0; i < regions.size(); i++){if (regions[i] == r){for (unsigned int j = i + 1; j < regions.size(); j++){regions[j-1] = regions[j];layers[j-1] = layers[j];}regions.pop_back();layers.pop_back();int sx0 = 0;int sy0 = 0;int ex0 = 0;int ey0 = 0;const int term_colors[MAX_TERM_COL][3] =const int map_colors[MAX_MAP_COL][3] =#include "AppHdr.h"#include "debug.h"/** File: guic-win.cc* Summary: 1) Image manipulation routines* 2) WinClass and RegionClass system independent imprementaions* see guic-*.cc for system dependent implementations* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <X11/Xlib.h>#include <X11/X.h>#include <X11/Xutil.h>#include <X11/Xlocale.h>#include <X11/keysym.h>#include <X11/keysymdef.h>#include <X11/Xmd.h>#include "guic.h"static Display *display;static int screen;static GC term_gc[MAX_TERM_COL];static GC map_gc[MAX_MAP_COL];static unsigned long term_pix[MAX_TERM_COL];static unsigned long map_pix[MAX_MAP_COL];static unsigned long pix_transparent;static unsigned long pix_hilite;static unsigned long pix_black;static unsigned long pix_rimcolor;static int x11_byte_per_pixel_ximage();unsigned int blue);static XImage *read_png(const char *fname);/*******************************************************/void WinClass::SysInit(){win = (Window)NULL;}void WinClass::SysDeinit(){}void RegionClass::SysInit(){font = NULL;}void RegionClass::SysDeinit(){if (font != NULL && !font_copied) XFreeFont(display, font);}void TextRegionClass::SysInit(int x, int y, int cx, int cy){}void TextRegionClass::SysDeinit(){}void TileRegionClass::SysInit(int mx0, int my0, int dx0, int dy0){}void TileRegionClass::SysDeinit(){}void MapRegionClass::SysInit(int x, int y, int o_x, int o_y){}void MapRegionClass::SysDeinit(){}/*** Large part of this routine was copied from Hengband ***/int ascent, descent, width;font = XLoadQueryFont(display, name);if (!font){fprintf(stderr,"Error! Can't load font %s\n",name);exit(1);}width = font->max_bounds.width;ascent = font->ascent;descent = font->descent;int i;XSetFont(display, term_gc[i], font->fid);fx = dx = width;fy = dy = ascent + descent;asc = ascent;font_copied = false;}void RegionClass::copy_font(RegionClass *r){fx = r->fx;fy = r->fy;dx = r->dx;dy = r->dy;asc = r->asc;font = r->font;font_copied = true;}void RegionClass::sys_flush(){XFlush(display);}void RegionClass::init_backbuf(){}void TextRegionClass::init_backbuf(){}void TileRegionClass::init_backbuf(){int x, y;backbuf = ImgCreateSimple(mx*dx, my*dy);for (x = 0; x < mx*dx; x++)for (y = 0; y < my*dy; y++)XPutPixel(backbuf, x, y, pix_black);}void TileRegionClass::resize_backbuf(){if (backbuf != NULL) ImgDestroy(backbuf);init_backbuf();}void RegionClass::resize_backbuf(){if (backbuf != NULL) ImgDestroy(backbuf);init_backbuf();}void MapRegionClass::init_backbuf(){int x, y;backbuf = ImgCreateSimple(mx*dx, my*dy);for (x = 0; x < mx*dx; x++)for (y = 0; y < my*dy; y++)XPutPixel(backbuf, x, y, pix_black);}void MapRegionClass::resize_backbuf(){if (backbuf != NULL)ImgDestroy(backbuf);init_backbuf();}void TextRegionClass::draw_string(int x, int y, unsigned char *buf,{XFillRectangle(display, win->win, term_gc[col>>4],x*dx+ox, y*dy+oy, dx * len, dy);XDrawString(display, win->win, term_gc[col&0x0f], x*dx+ox, y*dy+asc+oy,(char *)&cbuf[y*mx+x], len);}void TextRegionClass::draw_cursor(int x, int y){XDrawString(display, win->win, term_gc[0x0f], x*dx+ox, y*dy+asc+oy,"_", 1);sys_flush();}void TextRegionClass::erase_cursor(){WinClass *w = win;int x0 = cursor_x;int y0 = cursor_y;int width = 1;int adrs = y0 * mx + x0;int col = abuf[adrs];int x1 = x0;;XFillRectangle(display, w->win, term_gc[col>>4],x1*dx + ox, y0*dy +oy, dx*width, dy);XDrawString(display, w->win,term_gc[col&0x0f], x0*dx+ ox, y0*dy+asc+ oy,(char *)&cbuf[adrs], width );}void WinClass::clear(){fillrect(0, 0, wx, wy, PIX_BLACK);XFlush(display);}void RegionClass::clear(){fillrect(0, 0, wx, wy, PIX_BLACK);XFlush(display);}void TileRegionClass::clear(){RegionClass::clear();}void MapRegionClass::clear(){int i;RegionClass::clear();}void TextRegionClass::clear(){int i;{}RegionClass::clear();}void WinClass::create(char *name){if (!win){win = XCreateSimpleWindow(display, RootWindow(display,screen),XMapWindow(display, win);XSelectInput(display, win, ExposureMask | KeyPressMask| ButtonPressMask | ButtonReleaseMask | PointerMotionMask |LeaveWindowMask | EnterWindowMask | StructureNotifyMask );move(ox, oy);}elseresize(0,0);clear();}void WinClass::move(){XMoveWindow(display, win, ox, oy);}void WinClass::resize(){XResizeWindow(display, win, wx, wy);}void TileRegionClass::redraw(int x1, int y1, int x2, int y2){int wwx = x2-x1+1;int wwy = y2-y1+1;if (x1<0){wwx += x1;x1 = 0;}if (y1<0){wwy += y1;y1 = 0;}if (x2 >= mx*dx){wwx -= x2-mx*dx+1;}if (y2 >= my*dy){wwy -= y2-my*dy+1;}XPutImage(display, win->win, term_gc[0],backbuf, x1, y1, x1+ox, y1+oy, wwx, wwy);}void MapRegionClass::redraw(int x1, int y1, int x2, int y2){if (!flag)return;XPutImage(display, win->win, term_gc[0],backbuf, x1*dx, y1*dy,x1*dx+ox, y1*dy+oy,(x2-x1+1)*dx, (y2-y1+1)*dy);}if (!flag)return;{{{set_col(col, x, y);}}}redraw();XFlush(display);force_redraw = false;}/* XXXXX* img_type related*/bool ImgIsTransparentAt(img_type img, int x, int y){}void ImgSetTransparentPix(img_type img){pix_transparent = XGetPixel(img, 0, 0);}void ImgDestroy(img_type img){}img_type ImgCreateSimple(int wx, int wy){char *buf = (char *)malloc(x11_byte_per_pixel_ximage()* wx * wy);return(res);}img_type ImgLoadFile(const char *name){return read_png(name);}void ImgClear(img_type img){ASSERT(img != NULL);}// Copy internal image to another internal imagevoid ImgCopy(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, int copy){int x, y;int bpp = src->bytes_per_line / src->width;int bpl_s = src->bytes_per_line;int bpl_d = dest->bytes_per_line;{char *p_dest = (char *)(dest->data + bpl_d * dy + dx * bpp);memcpy(p_dest, p_src, wx * bpp);p_dest += bpl_d;}}{CARD8 *p_dest = (CARD8 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d;}}{CARD16 *p_dest = (CARD16 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}{CARD32 *p_dest = (CARD32 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}}// Copy internal image to another internal imagevoid ImgCopyH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, int copy){int x, y;int bpp = src->bytes_per_line / src->width;int bpl_s = src->bytes_per_line;int bpl_d = dest->bytes_per_line;{char *p_dest = (char *)(dest->data + bpl_d * dy + dx * bpp);memcpy(p_dest, p_src, wx * bpp);p_dest += bpl_d;}}{CARD8 *p_dest = (CARD8 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d;}}{CARD16 *p_dest = (CARD16 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}{CARD32 *p_dest = (CARD32 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}}// Copy internal image to another internal imagevoid ImgCopyMasked(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask){int x, y, count;int bpp = src->bytes_per_line / src->width;int bpl_s = src->bytes_per_line;int bpl_d = dest->bytes_per_line;count = 0;{CARD8 *p_dest = (CARD8 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d;}}{CARD16 *p_dest = (CARD16 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}{CARD32 *p_dest = (CARD32 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}}// Copy internal image to another internal imagevoid ImgCopyMaskedH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask){int x, y, count;int bpp = src->bytes_per_line / src->width;int bpl_s = src->bytes_per_line;int bpl_d = dest->bytes_per_line;count = 0;{CARD8 *p_dest = (CARD8 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d;}}{CARD16 *p_dest = (CARD16 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}{CARD32 *p_dest = (CARD32 *)(dest->data + bpl_d * dy + dx * bpp);//X11 specificp_dest[x] = pix_hilite;p_dest[x] = p_src[x];}p_dest += bpl_d/bpp;}}}void TileRegionClass::DrawPanel(int left, int top, int width, int height){framerect(left, top , left + width, top + height, PIX_WHITE);framerect(left + 1, top + 1, left + width, top + height, PIX_DARKGREY);fillrect (left + 1, top + 1, left + width - 1, top + height -1, PIX_LIGHTGREY);}void RegionClass::framerect(int left, int top, int right, int bottom,int color){XDrawRectangle(display, win->win, term_gc[color&0xf],ox+left, oy+top, right-left, bottom-top);}void TileRegionClass::framerect(int left, int top, int right, int bottom,int color){int x,y;int pix = term_pix[color];XPutPixel(backbuf, x, top, pix);XPutPixel(backbuf, x, bottom, pix);}XPutPixel(backbuf, left, y, pix);XPutPixel(backbuf, right, y, pix);}}void WinClass::fillrect(int left, int top, int right, int bottom,int color){XFillRectangle(display, win, term_gc[color&0xf],top, left, right-left+1, bottom-top+1);}void RegionClass::fillrect(int left, int top, int right, int bottom,int color){XFillRectangle(display, win->win, term_gc[color&0xf],ox+left, oy+top, right-left, bottom-top);}void TileRegionClass::fillrect(int left, int top, int right, int bottom,int color){int x,y;int pix = term_pix[color];}/********************************************/bool GuicInit(Display **d, int *s){int i;setlocale(LC_ALL, "");if (!display){fprintf(stderr,"Cannot open display\n");}screen=DefaultScreen(display);*d = display;*s = screen;// for text display{const int *c = term_colors[i];XSetForeground(display,term_gc[i], term_pix[i]);}// for text display{const int *c = map_colors[i];XSetForeground(display, map_gc[i], map_pix[i]);}// for Image manipulationpix_rimcolor = create_pixel(1,1,1);}void GuicDeinit(){int i;XFreeGC(display,term_gc[i]);XFreeGC(display,map_gc[i]);XCloseDisplay(display);}static int x11_byte_per_pixel_ximage(){int i = 1;int j = (DefaultDepth(display, screen) - 1) >> 2;return i;}unsigned int blue){Colormap cmap = DefaultColormapOfScreen(DefaultScreenOfDisplay(display));XColor xcolour;xcolour.green = green * 256;xcolour.flags = DoRed | DoGreen | DoBlue;XAllocColor(display, cmap, &xcolour);return (xcolour.pixel);}/*Copied from pngtopnm.c and modified by M.Itakura(mostly omitted and added a few lines)only color paletted image is handled*//*** pngtopnm.c -** read a Portable Network Graphics file and produce a portable anymap**** Copyright (C) 1995,1998 by Alexander Lehmann <alex@hal.rhein-main.de>** and Willem van Schaik <willem@schaik.com>**** Permission to use, copy, modify, and distribute this software and its** documentation for any purpose and without fee is hereby granted, provided** that the above copyright notice appear in all copies and that both that** copyright notice and this permission notice appear in supporting** documentation. This software is provided "as is" without express or** implied warranty.**** modeled after giftopnm by David Koblas and** with lots of bits pasted from libpng.txt by Guy Eric Schalnat*/#include "png.h"#define pm_message printf#define pm_error(x) {fprintf(stderr,x);return NULL;}# define TRUE 1# define FALSE 0# define NONE 0#define SIG_CHECK_SIZE 4XImage *read_png (const char *fname){}/* sBIT handling is very tricky. If we are extracting only the image, wevalues agree. If we extract the transparency/alpha mask, sBIT isirrelevant for trans and valid for alpha. If we mix both, themultiplication may result in values that require the normal bit depth,so we will use the sBIT info only for transparency, if we know that onlysolid and fully transparent is used */if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||info_ptr->color_type == PNG_COLOR_TYPE_RGB ||info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&(info_ptr->sig_bit.red != info_ptr->sig_bit.green ||for (i = 0 ; i < 256 ; i++)}}fclose(ifp);return res;free (png_image);free (png_ptr);free (info_ptr);for (y = 0 ; y < info_ptr->height ; y++)free (png_image[y]);for (y = 0; y < info_ptr->height; y++){png_pixel = png_image[y];for (x = 0; x < info_ptr->width; x++){c = *png_pixel;png_pixel++;XPutPixel(res, x, y, pix_table[c]);}res = ImgCreateSimple(info_ptr->width, info_ptr->height);png_read_image (png_ptr, png_image);png_read_end (png_ptr, info_ptr);pix_table[i] = create_pixel(i, i, i);}info_ptr->palette[i].green, info_ptr->palette[i].blue);}else if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY){//X11if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE){//X11for (i = 0 ; i < info_ptr->num_palette ; i++)pix_table[i] = create_pixel(info_ptr->palette[i].red,info_ptr->sig_bit.red != info_ptr->sig_bit.blue) ){"supported");info_ptr->bit_depth);}else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE&& info_ptr->sig_bit.red < 255){for (i = 0 ; i < info_ptr->num_palette ; i++){}else if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY|| info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)&& info_ptr->sig_bit.gray < info_ptr->bit_depth){}}png_set_shift (png_ptr, &(info_ptr->sig_bit));info_ptr->palette[i].red >>= (8 - info_ptr->sig_bit.red);info_ptr->palette[i].green >>= (8 - info_ptr->sig_bit.green);info_ptr->palette[i].blue >>= (8 - info_ptr->sig_bit.blue);}pm_message ("writing file with %d bit resolution",pm_message ("different bit depths for color channels not "if (info_ptr->valid & PNG_INFO_sBIT){can use the sBIT info for greyscale and color images, if the threeif (info_ptr->bit_depth < 8)png_set_packing (png_ptr);free (png_image);free (png_ptr);free (info_ptr);pm_error ("couldn't alloc space for image");}for (y = 0 ; y < info_ptr->height ; y++){png_image[y] = (png_byte *)malloc (linesize);if (png_image[y] == NULL){for (x = 0; x < y; x++)free (png_image[x]);if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)linesize *= 2;else if (info_ptr->color_type == PNG_COLOR_TYPE_RGB)linesize *= 3;else if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)linesize *= 4;if (info_ptr->bit_depth == 16)linesize = 2 * info_ptr->width;elselinesize = info_ptr->width;png_image = (png_byte **)malloc (info_ptr->height * sizeof (png_byte*));if (png_image == NULL){free (png_ptr);free (info_ptr);pm_error ("couldn't alloc space for image");}png_init_io (png_ptr, ifp);png_set_sig_bytes (png_ptr, SIG_CHECK_SIZE);png_read_info (png_ptr, info_ptr);if (setjmp (png_ptr->jmpbuf)){png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);free (png_ptr);free (info_ptr);pm_error ("setjmp returns error condition");}info_ptr = png_create_info_struct (png_ptr);if (info_ptr == NULL){png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL);pm_error ("cannot allocate LIBPNG structures");}png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);if (png_ptr == NULL)pm_error ("cannot allocate LIBPNG structure");if (fread (sig_buf, 1, SIG_CHECK_SIZE, ifp) != SIG_CHECK_SIZE)pm_error ("input file empty or too short");if (png_sig_cmp ((unsigned char *)sig_buf, (png_size_t) 0,(png_size_t) SIG_CHECK_SIZE) != 0){pm_error ("input file not a PNG file");}if (!ifp){fprintf(stderr, "File not found: %s", fname);return NULL;}FILE *ifp = fopen(fname,"r");//X11XImage *res;unsigned long pix_table[256];char sig_buf [SIG_CHECK_SIZE];png_struct *png_ptr;png_info *info_ptr;png_byte **png_image;png_byte *png_pixel;unsigned int x, y;int linesize;png_uint_16 c;unsigned int i;xcolour.blue = blue * 256;xcolour.red = red * 256;unsigned long create_pixel(unsigned int red, unsigned int green,while (j >>= 1){i <<= 1;}for (i = 0; i < MAX_MAP_COL; i++)for (i = 0; i < MAX_TERM_COL; i++)return (true);pix_black = term_pix[PIX_BLACK] ;pix_hilite = term_pix[PIX_LIGHTMAGENTA] ;map_pix[i] = create_pixel(c[0], c[1], c[2]);map_gc[i] = XCreateGC(display, RootWindow(display,screen), 0, 0);for (i = 0; i < MAX_MAP_COL; i++)term_pix[i] = create_pixel(c[0], c[1], c[2]);term_gc[i] = XCreateGC(display, RootWindow(display,screen), 0, 0);for (i = 0; i < MAX_TERM_COL; i++)return (false);display = XOpenDisplay("");for (x = left; x <= right; x++)for (y = top; y <= bottom; y++)XPutPixel(backbuf, x, y, pix);ASSERT(left >= 0);ASSERT(top >= 0);ASSERT(right < mx*dx);ASSERT(bottom < my*dy);for (y = top+1; y < bottom; y++){for (x = left; x <= right; x++){p_src += bpl_s/bpp;count++;else if (p_src[x] != pix_transparent && mask[count] == 0)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD32 *p_src = (CARD32 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 4)p_src += bpl_s/bpp;count++;else if (p_src[x] != pix_transparent && mask[count] == 0)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD16 *p_src = (CARD16 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 2)p_src += bpl_s;count++;else if (p_src[x] != pix_transparent && mask[count] == 0)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD8 *p_src = (CARD8 *)(src->data + bpl_s * sy + sx * bpp);if (bpp <= 1)ASSERT(sx >= 0);ASSERT(sy >= 0);ASSERT(sx + wx <= src->width);ASSERT(sy + wy <= src->height);ASSERT(dx >= 0);ASSERT(dy >= 0);ASSERT(dx + wx <= dest->width);ASSERT(dy + wy <= dest->height);p_src += bpl_s/bpp;count++;if (p_src[x] != pix_transparent && mask[count] == 0)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD32 *p_src = (CARD32 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 4)p_src += bpl_s/bpp;count++;if (p_src[x] != pix_transparent && mask[count] == 0)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD16 *p_src = (CARD16 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 2)p_src += bpl_s;count++;if (p_src[x] != pix_transparent && mask[count] == 0)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD8 *p_src = (CARD8 *)(src->data + bpl_s * sy + sx * bpp);if (bpp <= 1)ASSERT(sx >= 0);ASSERT(sy >= 0);ASSERT(sx + wx <= src->width);ASSERT(sy + wy <= src->height);ASSERT(dx >= 0);ASSERT(dy >= 0);ASSERT(dx + wx <= dest->width);ASSERT(dy + wy <= dest->height);p_src += bpl_s/bpp;else if (p_src[x] != pix_transparent)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD32 *p_src = (CARD32 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 4)p_src += bpl_s/bpp;else if (p_src[x] != pix_transparent)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD16 *p_src = (CARD16 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 2)p_src += bpl_s;else if (p_src[x] != pix_transparent)if (p_src[x] == pix_rimcolor)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD8 *p_src = (CARD8 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 1)p_src += bpl_s;for (y = 0; y < wy; y++){char *p_src = (char *)(src->data + bpl_s * sy + sx * bpp);if (copy == 1)ASSERT(sx >= 0);ASSERT(sy >= 0);ASSERT(sx + wx <= src->width);ASSERT(sy + wy <= src->height);ASSERT(dx >= 0);ASSERT(dy >= 0);ASSERT(dx + wx <= dest->width);ASSERT(dy + wy <= dest->height);p_src += bpl_s/bpp;if (p_src[x] != pix_transparent)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD32 *p_src = (CARD32 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 4)p_src += bpl_s/bpp;if (p_src[x] != pix_transparent)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD16 *p_src = (CARD16 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 2)p_src += bpl_s;if (p_src[x] != pix_transparent)for (y = 0; y < wy; y++){for (x = 0; x < wx; x++){CARD8 *p_src = (CARD8 *)(src->data + bpl_s * sy + sx * bpp);else if (bpp <= 1)p_src += bpl_s;for (y = 0; y < wy; y++){char *p_src = (char *)(src->data + bpl_s * sy + sx * bpp);if (copy == 1)ASSERT(sx >= 0);ASSERT(sy >= 0);ASSERT(sx + wx <= src->width);ASSERT(sy + wy <= src->height);ASSERT(dx >= 0);ASSERT(dy >= 0);ASSERT(dx + wx <= dest->width);ASSERT(dy + wy <= dest->height);for (x = 0; x < img->width; x++)for (y = 0; y < img->height; y++)XPutPixel(img, x, y, pix_transparent);int x, y;img_type res = XCreateImage(display, DefaultVisual(display, screen),DefaultDepth(display, screen),ZPixmap, 0, buf, wx, wy, 8, 0);if (wx == 0 || wy == 0)return NULL;if (img)XDestroyImage(img);return (pix_transparent == XGetPixel(img, x, y)) ? true : false;ASSERT(x >= 0);ASSERT(y >= 0);ASSERT(x < img->width);ASSERT(y < img->height);if (show_mark){for (int yy = 0; yy < dy * marker_length; yy++){map_pix[MAP_WHITE]);}for (int xx = 0; xx < dx * marker_length; xx++){map_pix[MAP_WHITE]);}}XPutPixel(backbuf, xx, old_mark_y*dy+dy/2 + y_margin,XPutPixel(backbuf, old_mark_x*dx+dx/2 + x_margin, yy,old_mark_x = mark_x;old_mark_y = mark_y;{XPutPixel(backbuf, x_margin + x*dx+xx,}y_margin + y*dy+yy, map_pix[col]);for (int xx = 0; xx < dx; xx++)for (int yy = 0; yy < dy; yy++)if (col != get_col(x, y) || force_redraw|| x < marker_length || y < marker_length)int col = ptr[x];unsigned char *ptr = &buf[y * (mx2 - x_margin)];for (int x = 0; x < mx - x_margin; x++)for (int y = 0; y < my - y_margin; y++)for (int xx = 0; xx < dx * marker_length; xx++){XPutPixel(backbuf, xx, old_mark_y*dy+dy/2 + y_margin,map_pix[MAP_BLACK]);}for (int yy = 0; yy < dy * marker_length; yy++){XPutPixel(backbuf, old_mark_x*dx+dx/2 + x_margin, yy,map_pix[MAP_BLACK]);}{void MapRegionClass::draw_data(unsigned char *buf, bool show_mark,int mark_x, int mark_y)XStoreName(display, win, CRAWL " " VERSION);10,10, wx, wy, 0,BlackPixel(display,screen), BlackPixel(display,screen));cbuf[i] = ' ';abuf[i] = 0;for (i = 0; i < mx*my; i++)for (i = 0; i < mx2*my2; i++)mbuf[i] = PIX_BLACK;if (!flag)return;if (!flag)return;int len, int col)for (i = 0; i < MAX_TERM_COL; i++)void RegionClass::init_font(const char *name){static unsigned long create_pixel(unsigned int red, unsigned int green,#include "version.h"#include "debug.h"#include "externs.h"#include "AppHdr.h"/** File: guic-x11.cc* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/
#include <windows.h>#include <commdlg.h>#include <commctrl.h>#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <memory.h>#include <tchar.h>// WinClass & RegionClass definitionsstatic HINSTANCE hInst;static int nCmdShow;// colorsstatic COLORREF term_pix[MAX_TERM_COL];BYTE pix_transparent;BYTE pix_black;BYTE pix_white;BYTE pix_magenta;BYTE pix_rimcolor;RGBQUAD RegionClass::std_palette[256];bool GuicInit(HINSTANCE h, int nCmd){int i;hInst = h;nCmdShow = nCmd;{}}void GuicDeinit(){}void WinClass::SysInit(){hWnd = NULL;}void WinClass::SysDeinit(){}void RegionClass::SysInit(){font = NULL;}void RegionClass::SysDeinit(){if (font != NULL && !font_copied) DeleteObject(font);}void RegionClass::sys_flush(){}void TextRegionClass::SysInit(int x, int y, int cx, int cy){dos_char = false;}void TextRegionClass::SysDeinit(){}void TileRegionClass::SysInit(int mx0, int my0, int dx0, int dy0){}void TileRegionClass::SysDeinit(){}void MapRegionClass::SysInit(int x, int y, int o_x, int o_y){}void MapRegionClass::SysDeinit(){}void RegionClass::init_font(const char *name, int height){int wid, hgt;LOGFONT lf;HFONT ftmp;strcpy(lf.lfFaceName, name);lf.lfHeight = height;lf.lfWidth = 0;lf.lfEscapement = 0;lf.lfOrientation = lf.lfEscapement;lf.lfWeight = FW_NORMAL;lf.lfItalic = FALSE;lf.lfUnderline = FALSE;lf.lfStrikeOut = FALSE;lf.lfOutPrecision = OUT_DEFAULT_PRECIS;lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;lf.lfQuality = DEFAULT_QUALITY;#ifdef JPlf.lfCharSet = (dos_char) ? OEM_CHARSET:SHIFTJIS_CHARSET;lf.lfPitchAndFamily= FF_DONTCARE|FIXED_PITCH;#elself.lfCharSet = (dos_char) ? OEM_CHARSET:ANSI_CHARSET;lf.lfPitchAndFamily= FF_MODERN|FIXED_PITCH;#endifftmp = CreateFontIndirect( &lf );if (!ftmp){}font = ftmp;wid = lf.lfWidth;hgt = lf.lfHeight;/* This part is taken from angband *//* Hack -- Unknown size */if (!wid || !hgt){HDC hdcDesktop;HFONT hfOld;TEXTMETRIC tm;/* all this trouble to get the cell size */hdcDesktop = GetDC(HWND_DESKTOP);hfOld = (HFONT)SelectObject(hdcDesktop, font);GetTextMetrics(hdcDesktop, &tm);SelectObject(hdcDesktop, hfOld);ReleaseDC(HWND_DESKTOP, hdcDesktop);/* Font size info */wid = tm.tmAveCharWidth;hgt = tm.tmHeight;}fx = dx = wid;fy = dy = hgt;}void RegionClass::change_font(const char *name, int height){if (font != NULL) DeleteObject(font);init_font(name, height);}void RegionClass::copy_font(RegionClass *r){fx = r->fx;fy = r->fy;dx = r->dx;dy = r->dy;font = r->font;}void RegionClass::set_std_palette(RGBQUAD *pPal){int i;{pix_black = i;pix_white = i;pix_magenta = i;pix_rimcolor = i;}std_palette[pix_transparent].rgbRed = 0;std_palette[pix_transparent].rgbGreen = 0;std_palette[pix_transparent].rgbBlue = 0;}void RegionClass::init_backbuf(RGBQUAD *pPal, int ncolor){int i;// first timeif (backbuf == NULL){// alloc for misc infobackbuf = (dib_pack *)GlobalAlloc(GPTR, sizeof(dib_pack));// alloc for header+palette databackbuf->pDib = (LPBITMAPINFO)GlobalAlloc(GPTR,(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)) );// set header data// set palette datafor (i = 0; i < ncolor; i++){// copy palette from given palette pPalbackbuf->pDib->bmiColors[i].rgbRed = pPal[i].rgbRed ;backbuf->pDib->bmiColors[i].rgbGreen = pPal[i].rgbGreen;backbuf->pDib->bmiColors[i].rgbBlue = pPal[i].rgbBlue ;}}// set dimensionbackbuf->pDib->bmiHeader.biWidth = mx*dx;backbuf->pDib->bmiHeader.biHeight = my*dy;backbuf->Width = mx * dx;backbuf->Height= my * dy;if (win != NULL){// this routine should be called after the window is initializedif (win->hWnd != NULL){HDC hdc1 = GetDC(0);HDC hdc2 = GetDC(win->hWnd);backbuf->hDib = CreateDIBSection(hdc1, backbuf->pDib,backbuf->hDC = CreateCompatibleDC(hdc2);SelectObject(backbuf->hDC, backbuf->hDib);ReleaseDC(win->hWnd, hdc2);ReleaseDC(0, hdc1);}}}void RegionClass::resize_backbuf(){int i;// discard it for resizeif (backbuf->hDC != NULL) DeleteDC(backbuf->hDC);if (backbuf->hDib != NULL) DeleteObject(backbuf->hDib);// set dimensionHDC hdc1 = GetDC(0);HDC hdc2 = GetDC(win->hWnd);// alloc a region of the windowbackbuf->hDib = CreateDIBSection(hdc1, backbuf->pDib,backbuf->hDC = CreateCompatibleDC(hdc2);SelectObject(backbuf->hDC, backbuf->hDib);ReleaseDC(win->hWnd, hdc2);ReleaseDC(0, hdc1);for (i = 0; i< mx*dx*my*dy; i++)*(backbuf->pDibBits + i) = pix_black;}void MapRegionClass::resize_backbuf(){RegionClass::resize_backbuf();}void TileRegionClass::resize_backbuf(){RegionClass::resize_backbuf();}void TextRegionClass::init_backbuf(){}void TileRegionClass::init_backbuf(RGBQUAD *pPal){int i;if (!pPal)elsefor (i = 0; i< mx*dx*my*dy; i++)*(backbuf->pDibBits + i) = pix_black;}void MapRegionClass::init_backbuf(){BYTE black = 0;RGBQUAD scol[MAX_MAP_COL];int i;{}// just resizeif (backbuf != NULL)RegionClass::init_backbuf(NULL, 0);elseRegionClass::init_backbuf(scol, MAX_MAP_COL);for (i = 0; i < MAX_MAP_COL; i++){black = i;}for (i = 0; i< mx*dx*my*dy; i++)}// defined to object, not to classvoid TextRegionClass::draw_string(int x, int y, unsigned char *buf,{HDC hdc = GetDC(win->hWnd);RECT rc;rc.bottom = rc.top + dy;SelectObject(hdc, font);SetBkColor(hdc, term_pix[col>>4]);SetTextColor(hdc, term_pix[col&0x0f]);ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,ReleaseDC(win->hWnd, hdc);}void TextRegionClass::draw_cursor(int x, int y){RECT rc;HDC hdc;int cx = x - cx_ofs;int cy = y - cy_ofs;SelectObject(hdc, font);rc.bottom = rc.top + dy;SetBkMode(hdc, TRANSPARENT);SetTextColor(hdc, term_pix[0x0f]);ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,ReleaseDC(win->hWnd, hdc);}int x0 = cursor_x;int y0 = cursor_y;int adrs = y0 * mx + x0;int col = abuf[adrs];RECT rc;SelectObject(hdc, font);//restore previous cursor cellrc.bottom = rc.top + dy;unsigned char rchar[3];SetBkColor(hdc, term_pix[col>>4]);SetTextColor(hdc, term_pix[col&0x0f]);rchar[0] = cbuf[adrs];#ifdef JPif ( (rchar[0]&0x80) && !dos_char /*_ismbblead( rchar[0])*/ ){rchar[1] = cbuf[adrs+1];rchar[2] = '\0';ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,}else#endif{rchar[1] = '\0';ExtTextOut(hdc, rc.left, rc.top, ETO_CLIPPED, &rc,}ReleaseDC(win->hWnd, hdc);}void WinClass::clear(){fillrect(0, 0, wx-1, wy-1, PIX_BLACK);}void RegionClass::clear(){fillrect(0, 0, wx-1, wy-1, PIX_BLACK);}void TileRegionClass::clear(){RegionClass::clear();}void MapRegionClass::clear(){RegionClass::clear();}void TextRegionClass::clear(){int i;{}RegionClass::clear();}BOOL WinClass::create(const char *name){RECT rc;rc.left = 0;rc.right = wx;rc.top = 0;rc.bottom = wy;//game_state = STAT_NORMAL;AdjustWindowRectEx(&rc,false, 0);if (hWnd == NULL){hWnd = CreateWindowEx(0, "CrawlList",name,ShowWindow( hWnd, nCmdShow );}clear();}void WinClass::move(){}void WinClass::resize(){RECT rc;rc.left = 0;rc.right = wx;rc.top = 0;rc.bottom = wy;AdjustWindowRectEx(&rc,false, 0);SetWindowPos(hWnd, 0, ox, oy,UpdateWindow( hWnd );}void TileRegionClass::redraw(int x1, int y1, int x2, int y2){if (!flag) return;if (!is_active()) return;HDC hdc = GetDC(win->hWnd);BitBlt(hdc, ox, oy, mx*dx, my*dy,backbuf->hDC, 0, 0, SRCCOPY);ReleaseDC(win->hWnd, hdc);}void MapRegionClass::redraw(int x1, int y1, int x2, int y2){if (!flag) return;if (!is_active()) return;BitBlt(hdc, ox, oy, dx*mx, dy*my,backbuf->hDC, 0, 0, SRCCOPY);ReleaseDC(win->hWnd, hdc);}LPBYTE ppix ,dpix;int inc_x, inc_y, inc_x0, inc_y0;int bufx = mx * dx;int bufy = my * dy;#define BUF_IDX(x,y, x1, y1) ((x)*dx-(y)*dy*bufx + (x1) - (y1)*bufx)// upper left cornerLPBYTE pDibBit0 = backbuf->pDibBits + bufx*(bufy-1);ppix = pDibBit0;inc_x0 = 1;{{{dpix = ppix;{{*dpix = col;dpix += inc_x0;}dpix += inc_y0;}}ppix += inc_x;}ppix += inc_y;}redraw();force_redraw = false;}LPBYTE dib_ref_pixel(dib_pack* dib, int x, int y){int w = ((3 + dib->Width)/4)*4;LPBYTE ref = dib->pDibBits + x + (dib->Height -1 -y) * w;}bool ImgIsTransparentAt(img_type img, int x, int y){}void ImgSetTransparentPix(img_type img){pix_transparent = (BYTE)*(img->pDibZero);}img_type ImgCreateSimple(int wx, int wy){dib_pack *ptr = (dib_pack *)GlobalAlloc(GPTR, sizeof(dib_pack));ptr->pDibBits = (LPBYTE)GlobalAlloc(GPTR, wx*wy );ptr->pDibZero = ptr->pDibBits + (wy -1)* wx;ptr->Width = wx;ptr->Height = wy;ptr->pDib = NULL;ptr->hDib = NULL;ptr->hDC = NULL;}void ImgDestroy(img_type img){GlobalFree(img);}img_type ImgLoadFile(const char *name){HANDLE fh;DWORD dummy;BITMAPFILEHEADER bmHead;int BitsSize;HDC hdc1;dib_pack *img;hdc1 = GetDC(0);if (!ReadFile(fh,&bmHead, sizeof(BITMAPFILEHEADER), &dummy, NULL))img = (dib_pack *) GlobalAlloc(GPTR, sizeof(dib_pack));img->pDib = (LPBITMAPINFO)GlobalAlloc(GPTR,(sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)) );if (img->pDib == NULL){GlobalFree(img);return NULL;}SetFilePointer(fh, sizeof(BITMAPFILEHEADER), NULL, FILE_BEGIN);{GlobalFree(img->pDib);GlobalFree(img);return NULL;}img->hDib = CreateDIBSection(hdc1, img->pDib, DIB_RGB_COLORS,(VOID **)&(img->pDibBits), NULL,0);if (img->hDib == NULL){GlobalFree(img->pDib);GlobalFree(img);return NULL;}BitsSize = bmHead.bfSize-bmHead.bfOffBits;SetFilePointer(fh, bmHead.bfOffBits, NULL, FILE_BEGIN);if (!ReadFile(fh, img->pDibBits, BitsSize, &dummy, NULL)){GlobalFree(img->hDib);GlobalFree(img->pDib);GlobalFree(img);return NULL;}img->Width = img->pDib->bmiHeader.biWidth ;img->Height = img->pDib->bmiHeader.biHeight;img->pDibZero = img->pDibBits + (img->Height - 1) * img->Width;ReleaseDC(0, hdc1);return img;}void ImgClear(img_type img){int i;for (i = 0; i< (img->Width * img->Height); i++)*(img->pDibBits + i) = pix_transparent;}// Copy internal image to another internal imagevoid ImgCopy(img_type src, int sx, int sy, int wx, int wy,{int x, y;BYTE pix;{}else{}}// Copy internal image to another internal imagevoid ImgCopyH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, int copy){int x, y;BYTE pix;{}else{}}// Copy internal image to another internal imagevoid ImgCopyMasked(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask){int x, y;BYTE pix;int count = 0;}// Copy internal image to another internal imagevoid ImgCopyMaskedH(img_type src, int sx, int sy, int wx, int wy,img_type dest, int dx, int dy, char *mask){int x, y;BYTE pix;int count = 0;}void WinClass::fillrect(int left, int top, int right, int bottom, int color){HDC hdc = GetDC(hWnd);HBRUSH curbrush;HDC curbrushhdc = NULL;curbrush = CreateSolidBrush(term_pix[color]);SelectObject(curbrushhdc, curbrush);FillRect(hdc, &currect, curbrush);DeleteObject(curbrush);DeleteDC(curbrushhdc);ReleaseDC(hWnd, hdc);}void TileRegionClass::DrawPanel(int left, int top, int width, int height){framerect(left, top , left + width, top + height, PIX_WHITE);framerect(left + 1, top + 1, left + width, top + height, PIX_DARKGREY);fillrect (left + 1, top + 1, left + width - 1, top + height -1, PIX_LIGHTGREY);}void RegionClass::framerect(int left, int top, int right, int bottom, int color){HDC hdc = GetDC(win->hWnd);HBRUSH curbrush;RECT currect;curbrush = CreateSolidBrush(term_pix[color]);SelectObject(curbrushhdc, curbrush);FrameRect(hdc, &currect, curbrush);DeleteObject(curbrush);DeleteDC(curbrushhdc);ReleaseDC(win->hWnd, hdc);}void TileRegionClass::framerect(int left, int top, int right, int bottom,int color){HDC dhdc = backbuf->hDC;HBRUSH curbrush;RECT currect;curbrush = CreateSolidBrush(term_pix[color]);SelectObject(curbrushhdc, curbrush);FrameRect(dhdc, &currect, curbrush);DeleteObject(curbrush);DeleteDC(curbrushhdc);}void RegionClass::fillrect(int left, int top, int right, int bottom, int color){HDC hdc = GetDC(win->hWnd);HBRUSH curbrush;RECT currect;curbrush = CreateSolidBrush(term_pix[color]);SelectObject(curbrushhdc, curbrush);FillRect(hdc, &currect, curbrush);DeleteObject(curbrush);DeleteDC(curbrushhdc);ReleaseDC(win->hWnd, hdc);}void TileRegionClass::fillrect(int left, int top, int right, int bottom,int color){HDC dhdc = backbuf->hDC;HBRUSH curbrush;RECT currect;curbrush = CreateSolidBrush(term_pix[color]);SelectObject(curbrushhdc, curbrush);FillRect(dhdc, &currect, curbrush);DeleteObject(curbrush);DeleteDC(curbrushhdc);}currect.left = left;currect.right = right;currect.top = top;currect.bottom = bottom;HDC curbrushhdc = NULL;currect.left = sx + left;currect.right = sx + right;currect.top = sy + top;currect.bottom = sy + bottom;HDC curbrushhdc = NULL;currect.left = left;currect.right = right;currect.top = top;currect.bottom = bottom;HDC curbrushhdc = NULL;currect.left = sx + left;currect.right = sx + right;currect.top = sy + top;currect.bottom = sy + bottom;HDC curbrushhdc = NULL;currect.left = left;currect.right = right;currect.top = top;currect.bottom = bottom;RECT currect;for (y = 0; y < wy; y++)for (x = 0; x < wx; x++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );if (pix == pix_rimcolor)pix = pix_magenta;*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;count++;}if (mask[count] == 0 && pix != pix_transparent)for (y = 0; y < wy; y++)for (x = 0; x < wx; x++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;count++;}if (mask[count] == 0 && pix != pix_transparent)for (x = 0; x < wx; x++)for (y = 0; y < wy; y++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );if (pix == pix_rimcolor)pix = pix_magenta;if (pix != pix_transparent)*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;}for (x = 0; x < wx; x++)for (y = 0; y < wy; y++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );if (pix == pix_rimcolor) pix = pix_magenta;*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;}if (copy)for (x = 0; x < wx; x++)for (y = 0; y < wy; y++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );if (pix!=pix_transparent)*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;}for (x = 0; x < wx; x++)for (y = 0; y < wy; y++){pix = *( dib_ref_pixel(src, sx+x, sy+y) );*( dib_ref_pixel(dest, dx+x, dy+y) ) = pix;}if (copy)img_type dest, int dx, int dy, int copy)CloseHandle(fh);if (!ReadFile(fh, img->pDib,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD),&dummy, NULL))if (!img)return NULL;return NULL;SetFilePointer(fh, 0, NULL, FILE_BEGIN);fh = CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);if (fh == INVALID_HANDLE_VALUE)return NULL;if (img->hDC)DeleteDC(img->hDC);if (img->hDib)DeleteObject(img->hDib);if (img->pDib)GlobalFree(img->pDib);if (!img)return;return (ptr);if (wx == 0 || wy == 0)return NULL;if (pix_transparent == *( dib_ref_pixel(img, x, y) ))return (false);return (true);return (ref);//// img_type related//for (int j = 0; j < dx * marker_length; j++)*(pDibBit0 + BUF_IDX(0, mark_y, j, dy/2 + y_margin)) = MAP_WHITE;}old_mark_x = mark_x;old_mark_y = mark_y;if (show_mark){// draw new markersfor (int j = 0; j < dy * marker_length; j++)*(pDibBit0 + BUF_IDX(mark_x, 0, dx/2 + x_margin, j)) = MAP_WHITE;set_col(col, i, j);for (int x = 0; x < dx; x++)for (int y = 0; y < dy; y++)if ( col != get_col(i,j) || force_redraw|| i < marker_length || j < marker_length)int col = (j >= my2 - y_margin || i >= mx2 - x_margin) ?MAP_BLACK : ptr[i];unsigned char *ptr = &buf[j * (mx2 - x_margin)];for (int i = 0; i < mx2; i++)force_redraw = true;dpix = ppix;for (int j = 0; j < my2; j++)for (int j = 0; j < dx * marker_length; j++)*(pDibBit0 + BUF_IDX(0, old_mark_y, j, dy/2 + y_margin)) = MAP_BLACK;// erase old markersfor (int j = 0; j < dy * marker_length; j++)*(pDibBit0 + BUF_IDX(old_mark_x, 0, dx/2 + x_margin, j)) = MAP_BLACK;inc_y0 = - dx * inc_x0 + BUF_IDX(0, 0, 0, 1);inc_y = - mx2 * inc_x + BUF_IDX(0, 1, 0, 0);inc_x = dx;bufx = (bufx+3)/4;bufx *= 4;if (!flag)return;{void MapRegionClass::draw_data(unsigned char *buf, bool show_mark,int mark_x, int mark_y)HDC hdc = GetDC(win->hWnd);rc.right - rc.left,rc.bottom - rc.top,SWP_NOMOVE);(WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX| WS_CAPTION | WS_VISIBLE),SetWindowPos(hWnd, 0, ox, oy, wx, wy, SWP_NOSIZE);UpdateWindow( hWnd );return (TRUE);if (!hWnd)return (FALSE);(WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX| WS_CAPTION | WS_VISIBLE),ox, oy, //posrc.right - rc.left, rc.bottom - rc.top, //sizeHWND_DESKTOP, NULL, hInst, NULL);(WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX| WS_CAPTION | WS_VISIBLE),if ( GetSystemMetrics(SM_CYSCREEN) < (oy + wy) )oy = 0;if ( GetSystemMetrics(SM_CXSCREEN) < (ox + wx) )ox = 0;cbuf[i] = ' ';abuf[i] = 0;for (i = 0; i < mx*my; i++)for (int i = 0; i < mx2*my2; i++)mbuf[i] = PIX_BLACK;(char *)&rchar, 1, NULL);(char *)&rchar, 2, NULL);rc.left = ox + x0 * dx;rc.right = rc.left + (2 * dx);rc.top = oy + y0 * dy;HDC hdc = GetDC(win->hWnd);if (!flag)return;void TextRegionClass::erase_cursor(){"_ ", 2, NULL);rc.left = ox + cx * dx ;rc.right = rc.left + (2 * dx);rc.top = oy + cy * dy;hdc = GetDC(win->hWnd);if (!flag)return;(char *)buf, len, NULL);rc.left = ox + x * dx;rc.right = rc.left + len * dx;rc.top = oy + y * dy;int len, int col)*(backbuf->pDibBits + i) = black;}if (backbuf->pDib->bmiColors[i].rgbRed == 0&& backbuf->pDib->bmiColors[i].rgbGreen == 0&& backbuf->pDib->bmiColors[i].rgbBlue == 0){scol[i].rgbBlue = map_colors[i][2];scol[i].rgbGreen = map_colors[i][1];scol[i].rgbRed = map_colors[i][0];scol[i].rgbReserved = 0;for (i = 0; i < MAX_MAP_COL; i++)RegionClass::init_backbuf(pPal, 256);RegionClass::init_backbuf(std_palette, 256);/* not used */backbuf->pDibZero = (backbuf->pDibBits+ (backbuf->Height -1) * backbuf->Width);DIB_RGB_COLORS, (VOID **)&(backbuf->pDibBits), NULL, 0);backbuf->pDib->bmiHeader.biWidth = mx*dx;backbuf->pDib->bmiHeader.biHeight = my*dy;backbuf->Width = mx * dx;backbuf->Height = my * dy;backbuf->pDibZero = (backbuf->pDibBits+ (backbuf->Height -1) * backbuf->Width);DIB_RGB_COLORS, (VOID **)&(backbuf->pDibBits), NULL, 0);// alloc a region of the windowbackbuf->pDib->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);backbuf->pDib->bmiHeader.biPlanes = 1;backbuf->pDib->bmiHeader.biBitCount = 8;backbuf->pDib->bmiHeader.biCompression = BI_RGB;backbuf->pDib->bmiHeader.biSizeImage = 0;backbuf->pDib->bmiHeader.biXPelsPerMeter = 0;backbuf->pDib->bmiHeader.biYPelsPerMeter = 0;backbuf->pDib->bmiHeader.biClrUsed = 0;backbuf->pDib->bmiHeader.biClrImportant = 0;}if (pPal[i].rgbRed == 1&& pPal[i].rgbGreen == 1&& pPal[i].rgbBlue == 1){}if (pPal[i].rgbRed == 255&& pPal[i].rgbGreen == 0&& pPal[i].rgbBlue == 255){}if (pPal[i].rgbRed == 255&& pPal[i].rgbGreen == 255&& pPal[i].rgbBlue == 255){}if (pPal[i].rgbRed == 0&& pPal[i].rgbGreen == 0&& pPal[i].rgbBlue == 0){std_palette[i].rgbRed = pPal[i].rgbRed ;std_palette[i].rgbGreen = pPal[i].rgbGreen;std_palette[i].rgbBlue = pPal[i].rgbBlue ;for (i = 0; i < 256; i++)if (font) return;exit(1);return (true);term_pix[i] = PALETTERGB( c[0], c[1], c[2] );int *c = (int *)&term_colors[i];for (i = 0; i < MAX_TERM_COL; i++)/** File: guic-win.cc* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/#include "AppHdr.h"#include "debug.h"#include "externs.h"#include "guic.h"
}#ifdef USE_TILEstatic void _update_minimap(int x, int y){int object = env.map[x][y].object;map_feature f = (object >= DNGN_START_OF_MONSTERS) ? MF_MONS_HOSTILE :Feature[object].minimap;if (f == MF_SKIP)f = Feature[grd[x][y]].minimap;ASSERT(f < MF_MAX);tiles.update_minimap(x, y, f);
// Highlight item. XXX: Doesn't work, unfortunately.const coord_def ep = grid2view(coord_def(item.x, item.y));tile_place_cursor(ep.x-1,ep.y-1,true);
const coord_def gc = coord_def(item.x, item.y);tiles.place_cursor(CURSOR_TUTORIAL, gc);tiles.add_text_tag(TAG_TUTORIAL, item.name(DESC_CAP_A), gc);
/** File: tiletex.h* Summary: PNG and texture loading functionality* Written by: Enne Walker*/#ifndef TILETEX_H#define TILETEX_Henum TextureID{TEX_DUNGEON,TEX_DEFAULT,TEX_DOLL,TEX_TITLE,TEX_MAX};class GenericTexture{public:GenericTexture();virtual ~GenericTexture();enum MipMapOptions{MIPMAP_CREATE,MIPMAP_NONE,MIPMAP_MAX};// Arbitrary post-load texture processingtypedef bool(*tex_proc_func)(unsigned char *pixels, unsigned int w,unsigned int h);bool load_texture(const char *filename, MipMapOptions mip_opt,tex_proc_func proc = NULL);bool load_texture(unsigned char *pixels, unsigned int w, unsigned int h,MipMapOptions mip_opt);void unload_texture();unsigned int width() const { return m_width; }unsigned int height() const { return m_height; }void bind();protected:unsigned int m_handle;unsigned int m_width;unsigned int m_height;};class TilesTexture : public GenericTexture{public:void get_texcoord(int idx, float &x, float &y, float &wx, float &wy);void get_texcoord_doll(int part, int idx, int ymax, float &x, float &y, float &wx, float &wy, int &wx_pix, int &wy_pix, int &ox, int &oy);};#endif
#include "AppHdr.h"#include "tiles.h"#include "tiletex.h"#include <SDL.h>#include <SDL_opengl.h>#include <SDL_image.h>GenericTexture::GenericTexture() :m_handle(0),m_width(0),m_height(0){}GenericTexture::~GenericTexture(){unload_texture();}void GenericTexture::unload_texture(){glDeleteTextures(1, (GLuint*)&m_handle);}bool GenericTexture::load_texture(const char *filename,GenericTexture::MipMapOptions mip_opt,tex_proc_func proc){char acBuffer[512];// TODO enne - use Crawl's helper functions to find images...strcpy(acBuffer, "dat/tiles/");strcat(acBuffer, filename);SDL_Surface *img = IMG_Load(acBuffer);if (!img){printf("Warning: couldn't load file '%s'.\n", acBuffer);return false;}unsigned int bpp = img->format->BytesPerPixel;glPixelStorei(GL_UNPACK_ALIGNMENT, bpp);// Determine texture formatunsigned char *pixels = (unsigned char*)img->pixels;int new_width = img->w;int new_height = img->h;GLenum texture_format;if (bpp == 4){if (img->format->Rmask == 0x000000ff)texture_format = GL_RGBA;elsetexture_format = GL_BGRA;}else if (bpp == 3){if (img->format->Rmask == 0x000000ff)texture_format = GL_RGB;elsetexture_format = GL_BGR;}else if (bpp == 1){// need to depalettizeSDL_LockSurface(img);// Prefer power-of-two textures to avoid texture bleeding from// floating point error.// TODO enne - convert non-palettized to power-of-2 as well?new_width = 1;while (new_width < img->w)new_width *= 2;new_height = 1;while (new_height < img->h)new_height *= 2;pixels = new unsigned char[4 * new_width * new_height];SDL_Palette* pal = img->format->palette;ASSERT(pal);ASSERT(pal->colors);// Find transparent colour// TODO enne - this should probably be removed from rltiles// TODO enne - is there more than one transparent color??int trans_index = -1;for (int p = 0; p < pal->ncolors ; p++){if (pal->colors[p].r == 71 &&pal->colors[p].g == 108 &&pal->colors[p].b == 108){trans_index = p;break;}}int src = 0;int dest = 0;for (int y = 0; y < img->h; y++){int x;for (x = 0; x < img->w; x++){int index = ((unsigned char*)img->pixels)[src++];pixels[dest*4 ] = pal->colors[index].r;pixels[dest*4 + 1] = pal->colors[index].g;pixels[dest*4 + 2] = pal->colors[index].b;pixels[dest*4 + 3] = (index == trans_index) ? 0 : 255;dest++;}while (x++ < new_width){// Extend to the right with transparent pixelspixels[dest*4 ] = 0;pixels[dest*4 + 1] = 0;pixels[dest*4 + 2] = 0;pixels[dest*4 + 3] = 0;dest++;}}while (dest < new_width * new_height){// Extend down with transparent pixelspixels[dest*4 ] = 0;pixels[dest*4 + 1] = 0;pixels[dest*4 + 2] = 0;pixels[dest*4 + 3] = 0;dest++;}SDL_UnlockSurface(img);bpp = 4;texture_format = GL_RGBA;}else{printf("Warning: unsupported format, bpp = %d for '%s'\n",bpp, acBuffer);return false;}bool success = false;if (!proc || proc(pixels, new_width, new_height)){success |= load_texture(pixels, new_width, new_height, mip_opt);}// If conversion has occurred, delete converted data.if (pixels != img->pixels)delete pixels;SDL_FreeSurface(img);return success;}bool GenericTexture::load_texture(unsigned char *pixels, unsigned int new_width,unsigned int new_height,GenericTexture::MipMapOptions mip_opt){if (!pixels || !new_width || !new_height)return false;// Assumptions...const unsigned int bpp = 4;const GLenum texture_format = GL_RGBA;const GLenum format = GL_UNSIGNED_BYTE;m_width = new_width;m_height = new_height;glGenTextures(1, (GLuint*)&m_handle);glBindTexture(GL_TEXTURE_2D, m_handle);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);if (mip_opt == MIPMAP_CREATE){glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);gluBuild2DMipmaps(GL_TEXTURE_2D, bpp, m_width, m_height,texture_format, format, pixels);}else{glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexImage2D(GL_TEXTURE_2D, 0, bpp, m_width, m_height, 0,texture_format, format, pixels);}return true;}void GenericTexture::bind(){ASSERT(m_handle);glBindTexture(GL_TEXTURE_2D, m_handle);}void TilesTexture::get_texcoord_doll(int part, int idx, int ymax, float &x, float &y, float &wx, float &wy, int &wx_pix, int &wy_pix, int &ox, int &oy){int tile_idx = tilep_parts_start[part];int nx = tilep_parts_nx[part];int ny = tilep_parts_ny[part];ox = tilep_parts_ox[part];oy = tilep_parts_oy[part];wx_pix = TILE_X / nx;wy_pix = TILE_Y / ny;if (!idx){wy = -1;return;}idx--;tile_idx += idx / (nx * ny);if (oy + wy_pix > ymax)wy_pix -= oy + wy_pix - ymax;int xs = (tile_idx % TILEP_PER_ROW) * TILE_X;int ys = (tile_idx / TILEP_PER_ROW) * TILE_Y;xs += (idx % nx) * TILE_X / nx;ys += ((idx / nx) % ny) * TILE_Y / ny;x = xs / (float)m_width;y = ys / (float)m_height;wx = wx_pix / (float)m_width;wy = wy_pix / (float)m_height;}void TilesTexture::get_texcoord(int idx, float &x, float &y,float &wx, float &wy){const unsigned int tile_size = 32;unsigned int tiles_per_row = m_width / tile_size;wx = tile_size / (float)m_width;wy = tile_size / (float)m_height;unsigned int row = idx / tiles_per_row;unsigned int col = idx % tiles_per_row;x = tile_size * col / (float)m_width;y = tile_size * row / (float)m_height;ASSERT(row >= 0);ASSERT(col >= 0);ASSERT(x + wx <= m_width);ASSERT(y + wy <= m_height);}
/** File: tilesdl.h* Summary: SDL-related functionality for the tiles port* Written by: Enne Walker*/#ifdef USE_TILE#ifndef TILESDL_H#define TILESDL_H#include "debug.h"#include "externs.h"#include "FixVec.h"#include "tilereg.h"// This struct defines all of the state that any particular rendering needs.// If other rendering states are needed, they should be added here so that// they do not introduce unneeded side effects for other parts of the code// that have not thought about turning that new state off.struct GLState{GLState();// vertex arraysbool array_vertex;bool array_texcoord;bool array_colour;// render statebool blend;bool texture;};enum key_mod{MOD_SHIFT = 0x1,MOD_CTRL = 0x2,MOD_ALT = 0x4};struct MouseEvent{enum mouse_event_type{PRESS,RELEASE,MOVE};enum mouse_event_button{NONE = 0x00,LEFT = 0x01,MIDDLE = 0x02,RIGHT = 0x04,SCROLL_UP = 0x08,SCROLL_DOWN = 0x10};// kind of eventmouse_event_type event;// if PRESS or RELEASE, the button pressedmouse_event_button button;// bitwise-or of buttons currently pressedunsigned short held;// bitwise-or of key mods currently pressedunsigned char mod;// location of events in pixels and in window coordinate spaceunsigned int px;unsigned int py;};class GLStateManager{public:static void init();static void set(const GLState& state);};class SDL_Surface;class FTFont;class TilesFramework{public:TilesFramework();virtual ~TilesFramework();bool initialise();void shutdown();void load_dungeon(unsigned int *tileb, int gx, int gy);void load_dungeon(int gx, int gy);int getch();int getch_ck();void resize();void clrscr();void message_out(int which_line, int colour, const char *s, int firstcol, bool newline);void cgotoxy(int x, int y, int region = GOTO_CRT);void clear_message_window();void update_minimap(int gx, int gy, map_feature f);void clear_minimap();void update_inventory();void update_menu_inventory(unsigned int slot, const item_def &item, bool selected, char key);void redraw();void place_cursor(cursor_type type, const coord_def &gc);void clear_text_tags(text_tag_type type);void add_text_tag(text_tag_type type, const std::string &tag,const coord_def &gc);bool initialise_items();const coord_def &get_cursor() const;protected:bool load_font(const char *font_file, int font_size);int handle_mouse(MouseEvent &event);// screen pixel dimensionscoord_def m_windowsz;// screen pixels per view cellcoord_def m_viewsc;SDL_Surface* m_context;bool m_fullscreen;enum LayerID{LAYER_NORMAL,LAYER_CRT,LAYER_TITLE,LAYER_MAX};class Layer{public:// Layers don't own these regionsstd::vector<Region*> m_regions;};Layer m_layers[LAYER_MAX];LayerID m_active_layer;// Normal layerDungeonRegion *m_region_tile;StatRegion *m_region_stat;MessageRegion *m_region_msg;MapRegion *m_region_map;InventoryRegion *m_region_self_inv;// Full-screen CRT layerCRTRegion *m_region_crt;InventoryRegion *m_region_menu_inv;FTFont *m_font;void do_layout();ImageManager m_image;// Mouse state.unsigned short m_buttons_held;unsigned char m_key_mod;coord_def m_mouse;unsigned int m_last_tick_moved;std::string m_tooltip;};// Main interface for tiles functionsextern TilesFramework tiles;#ifdef __MINGW32__#ifndef alloca// Srsly, MinGW, wtf?void *alloca(size_t);#endif#endif#endif#endif
#include "cio.h"#include "itemname.h"#include "items.h"#include "itemprop.h"#include "mon-util.h"#include "player.h"#include "stuff.h"#include "tiles.h"#include "tilesdl.h"#include "travel.h"#include "version.h"#include "tiledef-dngn.h"#include "tilefont.h"#include <SDL.h>#include <SDL_opengl.h>#include <SDL_image.h>// Note: these defaults should match the OpenGL defaultsGLState::GLState() :array_vertex(false),array_texcoord(false),array_colour(false),blend(false),texture(false){}void GLStateManager::init(){glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glClearColor(0.0, 0.0, 0.0, 1.0f);}void GLStateManager::set(const GLState& state){if (state.array_vertex)glEnableClientState(GL_VERTEX_ARRAY);elseglDisableClientState(GL_VERTEX_ARRAY);if (state.array_texcoord)glEnableClientState(GL_TEXTURE_COORD_ARRAY);elseglDisableClientState(GL_TEXTURE_COORD_ARRAY);if (state.array_colour){glEnableClientState(GL_COLOR_ARRAY);}else{glDisableClientState(GL_COLOR_ARRAY);// [enne] This should *not* be necessary, but the Linux OpenGL// drive that I'm using sets this to the last colour of the// colour array. So, we need to unset it here.glColor3f(1.0f, 1.0f, 1.0f);}if (state.texture)glEnable(GL_TEXTURE_2D);elseglDisable(GL_TEXTURE_2D);if (state.blend)glEnable(GL_BLEND);elseglDisable(GL_BLEND);}TilesFramework tiles;TilesFramework::TilesFramework() :m_windowsz(1024, 768),m_viewsc(0, 0),m_context(NULL),m_fullscreen(false),m_active_layer(LAYER_CRT),m_font(NULL),m_buttons_held(0),m_key_mod(0),m_mouse(-1, -1),m_last_tick_moved(0){}TilesFramework::~TilesFramework(){}void TilesFramework::shutdown(){delete m_region_tile;delete m_region_stat;delete m_region_msg;delete m_region_map;delete m_region_self_inv;delete m_region_crt;delete m_region_menu_inv;m_region_tile = NULL;m_region_stat = NULL;m_region_msg = NULL;m_region_map = NULL;m_region_self_inv = NULL;m_region_crt = NULL;m_region_menu_inv = NULL;for (unsigned int i = 0; i < LAYER_MAX; i++){m_layers[i].m_regions.clear();}SDL_Quit();}bool TilesFramework::initialise(){if (SDL_Init(SDL_INIT_VIDEO) != 0){printf ("Failed to initialise SDL: %s\n", SDL_GetError());return false;}SDL_EnableUNICODE(true);SDL_WM_SetCaption(CRAWL " " VERSION, CRAWL);SDL_Surface *icon = IMG_Load("dat/tiles/stone_soup_icon-32x32.png");if (!icon){printf ("Failed to load icon: %s\n", SDL_GetError());return false;}SDL_WM_SetIcon(icon, NULL);SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);unsigned int flags = SDL_OPENGL;if (m_fullscreen)flags |= SDL_FULLSCREEN;// TODO enne - add options for screen size and fullscreenm_context = SDL_SetVideoMode(m_windowsz.x, m_windowsz.y, 0, flags);if (!m_context){printf ("Failed to set video mode: %s\n", SDL_GetError());return false;}if (!m_image.load_textures())return false;// TODO enne - make this configurable (and fall back on default if fails)// TODO enne - use Crawl's dat file loading utilitiesconst char *font_file = "dat/tiles/VeraMono.ttf";const int font_size = 14;if (!load_font(font_file, font_size))return false;ASSERT(m_font);// TODO enne - grab these from optionsunsigned int map_pixsz = 4;// TODO enne - different font for tooltip and for dungeon tagsm_region_tile = new DungeonRegion(&m_image, m_font, TILE_X, TILE_Y);m_region_map = new MapRegion(map_pixsz);m_region_self_inv = new InventoryRegion(&m_image, TILE_X, TILE_Y);m_region_msg = new MessageRegion(m_font);m_region_stat = new StatRegion(m_font);m_region_crt = new CRTRegion(m_font);m_region_menu_inv = new InventoryRegion(&m_image, TILE_X, TILE_Y);m_layers[LAYER_NORMAL].m_regions.push_back(m_region_tile);m_layers[LAYER_NORMAL].m_regions.push_back(m_region_map);m_layers[LAYER_NORMAL].m_regions.push_back(m_region_self_inv);m_layers[LAYER_NORMAL].m_regions.push_back(m_region_msg);m_layers[LAYER_NORMAL].m_regions.push_back(m_region_stat);m_layers[LAYER_CRT].m_regions.push_back(m_region_crt);m_layers[LAYER_CRT].m_regions.push_back(m_region_menu_inv);cgotoxy(1, 1, GOTO_CRT);GLStateManager::init();resize();return true;}bool TilesFramework::load_font(const char *font_file, int font_size){m_font = new FTFont();if (!m_font->load_font(font_file, font_size)){delete m_font;m_font = NULL;printf("Failed to open font '%s'\n", font_file);return false;}return true;}void TilesFramework::load_dungeon(unsigned int *tileb, int gx, int gy){unsigned int ox = m_region_tile->mx/2;unsigned int oy = m_region_tile->my/2;m_region_tile->load_dungeon(tileb, gx - ox, gy - oy);coord_def win_start(gx - ox, gy - oy);coord_def win_end(gx + ox + 1, gy + oy + 1);m_region_map->set_window(win_start, win_end);}void TilesFramework::load_dungeon(int cx, int cy){int wx = m_region_tile->mx;int wy = m_region_tile->my;unsigned int *tb = (unsigned int*)alloca(sizeof(unsigned int) *wy * wx * 2);int count = 0;for (int y = 0; y < wy; y++){for (int x = 0; x < wx; x++){int fg;int bg;const coord_def gc(cx + x - wx/2,cy + y - wy/2);const coord_def ep = view2show(grid2view(gc));// mini "viewwindow" routineif (!map_bounds(gc)){fg = 0;bg = TILE_DNGN_UNSEEN;}else if (!crawl_view.in_grid_los(gc) || !env.show(ep)){fg = env.tile_bk_fg[gc.x][gc.y];bg = env.tile_bk_bg[gc.x][gc.y];if (bg == 0)bg |= TILE_DNGN_UNSEEN;bg |= tile_unseen_flag(gc);}else{fg = env.tile_fg[ep.x-1][ep.y-1];bg = env.tile_bg[ep.x-1][ep.y-1];}if (gc.x == cx && gc.y == cy)bg |= TILE_FLAG_CURSOR1;tb[count++] = fg;tb[count++] = bg;}}load_dungeon(tb, cx, cy);tiles.redraw();}void TilesFramework::resize(){do_layout();glMatrixMode(GL_PROJECTION);glLoadIdentity();// TODO enne - need better resizing// View size in pixels is (m_viewsc * crawl_view.viewsz)m_viewsc.x = 32;m_viewsc.y = 32;// For ease, vertex positions are pixel positions.glOrtho(0, m_windowsz.x, m_windowsz.y, 0, 0, 100);}static unsigned char _get_modifiers(SDL_keysym &keysym){// keysym.mod can't be used to keep track of the modifier state.// If shift is hit by itself, this will not include KMOD_SHIFT.// Instead, look for the key itself as a separate event.switch (keysym.sym){case SDLK_LSHIFT:case SDLK_RSHIFT:return MOD_SHIFT;case SDLK_LCTRL:case SDLK_RCTRL:return MOD_CTRL;case SDLK_LALT:case SDLK_RALT:return MOD_ALT;default:return 0;}}static int _translate_keysym(SDL_keysym &keysym){// This function returns the key that was hit. Returning zero implies that// the keypress (e.g. hitting shift on its own) should be eaten and not// handled.const int shift_offset = CK_SHIFT_UP - CK_UP;const int ctrl_offset = CK_CTRL_UP - CK_UP;int offset = 0;if (keysym.mod & KMOD_CTRL)offset = ctrl_offset;else if (keysym.mod & KMOD_SHIFT)offset = shift_offset;switch (keysym.sym){case SDLK_RETURN:return CK_ENTER;case SDLK_BACKSPACE:return CK_BKSP;case SDLK_ESCAPE:return CK_ESCAPE;case SDLK_DELETE:return CK_DELETE;case SDLK_UP:return CK_UP + offset;case SDLK_DOWN:return CK_DOWN + offset;case SDLK_LEFT:return CK_LEFT + offset;case SDLK_RIGHT:return CK_RIGHT + offset;case SDLK_INSERT:return CK_INSERT + offset;case SDLK_HOME:return CK_HOME + offset;case SDLK_END:return CK_END + offset;case SDLK_CLEAR:return CK_CLEAR + offset;case SDLK_PAGEUP:return CK_PGUP + offset;case SDLK_PAGEDOWN:return CK_PGDN + offset;default:break;}bool is_ascii = ((keysym.unicode & 0xFF80) == 0);return is_ascii ? keysym.unicode & 0x7F : 0;}int TilesFramework::getch(){// TODO enne - is there really a difference between these two functions??return getch_ck();}int TilesFramework::handle_mouse(MouseEvent &event){m_region_tile->place_cursor(CURSOR_MOUSE, Region::NO_CURSOR);// Note: the mouse event goes to all regions in the active layer because// we want to be able to start some GUI event (e.g. far viewing) and// stop if it moves to another region.int return_key = 0;for (unsigned int i = 0; i < m_layers[m_active_layer].m_regions.size(); i++){// TODO enne - what if two regions give a key?int key = 0;key = m_layers[m_active_layer].m_regions[i]->handle_mouse(event);if (key)return_key = key;}// Let regions take priority in any mouse mode.if (return_key)return return_key;// Handle "more" mode globally here, rather than duplicate across regions.if (mouse_control::current_mode() == MOUSE_MODE_MORE&& event.button == MouseEvent::LEFT&& event.event == MouseEvent::PRESS){return '\r';}// TODO enne - in what cases should the buttons be returned?#if 0// If nothing else, return the mouse button that was pressed.switch (event.button){case MouseEvent::LEFT:return CK_MOUSE_B1;case MouseEvent::RIGHT:return CK_MOUSE_B2;case MouseEvent::MIDDLE:return CK_MOUSE_B3;case MouseEvent::SCROLL_UP:return CK_MOUSE_B4;case MouseEvent::SCROLL_DOWN:return CK_MOUSE_B5;default:case MouseEvent::NONE:return 0;}#endifreturn 0;}static void _translate_event(const SDL_MouseMotionEvent &sdl_event,MouseEvent &tile_event){tile_event.held = MouseEvent::NONE;tile_event.event = MouseEvent::MOVE;tile_event.button = MouseEvent::NONE;tile_event.px = sdl_event.x;tile_event.py = sdl_event.y;// TODO enne - do we want the relative motion?}static void _translate_event(const SDL_MouseButtonEvent &sdl_event,MouseEvent &tile_event){tile_event.held = MouseEvent::NONE;tile_event.event = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ?MouseEvent::PRESS : MouseEvent::RELEASE;switch (sdl_event.button){case SDL_BUTTON_LEFT:tile_event.button = MouseEvent::LEFT;break;case SDL_BUTTON_RIGHT:tile_event.button = MouseEvent::RIGHT;break;case SDL_BUTTON_MIDDLE:tile_event.button = MouseEvent::MIDDLE;break;case SDL_BUTTON_WHEELUP:tile_event.button = MouseEvent::SCROLL_UP;break;case SDL_BUTTON_WHEELDOWN:tile_event.button = MouseEvent::SCROLL_DOWN;break;default:ASSERT(!"Unhandled button");tile_event.button = MouseEvent::NONE;break;}tile_event.px = sdl_event.x;tile_event.py = sdl_event.y;}int TilesFramework::getch_ck(){SDL_Event event;int key = 0;while (!key){unsigned int ticks = SDL_GetTicks();if (SDL_PollEvent(&event)){switch(event.type){case SDL_KEYDOWN:m_key_mod |= _get_modifiers(event.key.keysym);key = _translate_keysym(event.key.keysym);// If you hit a key, disable tooltips until the mouse// is moved again.m_last_tick_moved = ~0;break;case SDL_KEYUP:m_key_mod &= ~_get_modifiers(event.key.keysym);m_last_tick_moved = ~0;break;case SDL_MOUSEMOTION:{// Record mouse pos for tooltip timerif (m_mouse.x != event.motion.x|| m_mouse.y != event.motion.y){m_last_tick_moved = ticks;}m_mouse.x = event.motion.x;m_mouse.y = event.motion.y;MouseEvent mouse_event;_translate_event(event.motion, mouse_event);mouse_event.held = m_buttons_held;mouse_event.mod = m_key_mod;key = handle_mouse(mouse_event);}break;case SDL_MOUSEBUTTONUP:{MouseEvent mouse_event;_translate_event(event.button, mouse_event);m_buttons_held &= ~(mouse_event.button);mouse_event.held = m_buttons_held;mouse_event.mod = m_key_mod;key = handle_mouse(mouse_event);m_last_tick_moved = ticks;}break;case SDL_MOUSEBUTTONDOWN:{MouseEvent mouse_event;_translate_event(event.button, mouse_event);m_buttons_held |= mouse_event.button;mouse_event.held = m_buttons_held;mouse_event.mod = m_key_mod;key = handle_mouse(mouse_event);m_last_tick_moved = ticks;}break;case SDL_QUIT:// TODO enneexit(0);case SDL_USEREVENT:default:break;}}// TODO enne - outsource this valueunsigned int tooltip_ticks = 1000;bool show_tooltip = ((ticks - m_last_tick_moved > tooltip_ticks)&& ticks > m_last_tick_moved);if (show_tooltip){if (m_tooltip.empty()){for (unsigned int i = 0;i < m_layers[m_active_layer].m_regions.size(); i++){Region *reg = m_layers[m_active_layer].m_regions[i];if (!reg->inside(m_mouse.x, m_mouse.y))continue;if (reg->update_tip_text(m_tooltip))break;}}}else{m_tooltip.clear();}redraw();}return key;}void TilesFramework::do_layout(){const int map_stat_buffer = 5;// TODO enne - use optionsconst int crt_width = 80;const int crt_height = 30;const int map_margin = 2;// Size regions that we know aboutm_region_tile->resize(crawl_view.viewsz.x, crawl_view.viewsz.y);m_region_crt->resize(crt_width, crt_height);m_region_stat->resize(crawl_view.hudsz.x, crawl_view.hudsz.y);m_region_msg->resize(crawl_view.msgsz.x, crawl_view.msgsz.y);m_region_map->resize(GXM, GYM);// Place regions for normal layerconst int margin = 4;m_region_tile->place(0, 0, margin);m_region_msg->place(0, m_region_tile->ey, margin);int stat_col = m_region_tile->ex + map_stat_buffer;m_region_stat->place(stat_col, 0, 0);m_region_map->place(stat_col, m_region_stat->ey, map_margin);int inv_col = std::max(m_region_tile->ex, m_region_msg->ex);m_region_self_inv->place(inv_col, m_region_map->ey, 0);m_region_self_inv->resize_to_fit(m_windowsz.x -m_region_self_inv->sx,m_windowsz.y -m_region_self_inv->sy);// Place regions for crt layerm_region_crt->place(0, 0, margin);m_region_menu_inv->place(0, m_region_crt->ey, margin);m_region_menu_inv->resize_to_fit(m_windowsz.x, m_windowsz.y -m_region_menu_inv->sy);}void TilesFramework::clrscr(){TextRegion::cursor_region = NULL;if (m_region_stat)m_region_stat->clear();if (m_region_msg)m_region_msg->clear();if (m_region_crt)m_region_crt->clear();if (m_region_menu_inv)m_region_menu_inv->clear();cgotoxy(1,1);}void TilesFramework::message_out(int which_line, int colour, const char *s, int firstcol, bool newline){if (!firstcol)firstcol = Options.delay_message_clear ? 2 : 1;cgotoxy(firstcol, which_line + 1, GOTO_MSG);textcolor(colour);cprintf("%s", s);if (newline && which_line == crawl_view.msgsz.y - 1)m_region_msg->scroll();}void TilesFramework::clear_message_window(){m_region_msg->clear();m_active_layer = LAYER_NORMAL;}void TilesFramework::cgotoxy(int x, int y, int region){if (region == GOTO_LAST){// nothing}else if (region == GOTO_CRT){m_active_layer = LAYER_CRT;TextRegion::text_mode = m_region_crt;}else if (region == GOTO_MSG){m_active_layer = LAYER_NORMAL;TextRegion::text_mode = m_region_msg;}else if (region == GOTO_STAT){m_active_layer = LAYER_NORMAL;TextRegion::text_mode = m_region_stat;}TextRegion::cgotoxy(x, y);}void TilesFramework::redraw(){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glScalef(m_viewsc.x, m_viewsc.y, 1.0f);for (unsigned int i = 0; i < m_layers[m_active_layer].m_regions.size(); i++){m_layers[m_active_layer].m_regions[i]->render();}// Draw tooltipif (!m_tooltip.empty()){const coord_def min_pos(0, 0);m_font->render_string(m_mouse.x, m_mouse.y - 2, m_tooltip.c_str(),min_pos, m_windowsz, WHITE, false, 150,BLUE, 5);}SDL_GL_SwapBuffers();}void TilesFramework::update_minimap(int gx, int gy, map_feature f){if (!player_in_mappable_area())return;coord_def gc(gx, gy);if (you.pos() == gc){f = MF_PLAYER;}else if (f == MF_MONS_HOSTILE && mgrd[gx][gy] != NON_MONSTER){const int grid = mgrd[gx][gy];if (mons_friendly(&menv[grid]))f = MF_MONS_FRIENDLY;else if (mons_neutral(&menv[grid]))f = MF_MONS_NEUTRAL;else if (mons_class_flag(menv[grid].type, M_NO_EXP_GAIN))f = MF_MONS_NO_EXP;}else if (f == MF_FLOOR || f == MF_MAP_FLOOR){if (is_exclude_root(gc))f = MF_EXCL_ROOT;else if (is_excluded(gc))f = MF_EXCL;}m_region_map->set(gx, gy, f);}void TilesFramework::clear_minimap(){m_region_map->clear();}static void _fill_item_info(InventoryTile &desc, const item_def &item){desc.tile = tileidx_item(item);int type = item.base_type;if (type == OBJ_FOOD || type == OBJ_SCROLLS|| type == OBJ_POTIONS || type == OBJ_MISSILES){// -1 specifies don't display anythingdesc.quantity = item.quantity == 1 ? -1 : item.quantity;}else if (type == OBJ_WANDS&& ((item.flags & ISFLAG_KNOW_PLUSES)|| item.plus2 == ZAPCOUNT_EMPTY)){desc.quantity = item.plus;}else{desc.quantity = -1;}desc.flag = 0;if (item_cursed(item) && item_ident(item, ISFLAG_KNOW_CURSE))desc.flag |= TILEI_FLAG_CURSE;if (item_type_tried(item))desc.flag |= TILEI_FLAG_TRIED;if (item.x != -1)desc.flag |= TILEI_FLAG_FLOOR;}void TilesFramework::update_inventory(){std::vector<InventoryTile> inv;if (!Options.tile_show_items)return;unsigned int max_pack_row = (ENDOFPACK-1) / m_region_self_inv->mx + 1;max_pack_row = std::min(m_region_self_inv->my - 1, max_pack_row);unsigned int max_pack_items = max_pack_row * m_region_self_inv->mx;// TODO enne - document that '.' and '_' no longer work// TODO enne - if all inventory and ground can't fit, allow ground// and inventory items on the same row.// item.base_type <-> char conversion tableconst static char *obj_syms = ")([/%#?=!#+\\0}x";for (unsigned int c = 0; c < strlen(Options.tile_show_items); c++){if (inv.size() >= max_pack_items)break;const char *find = strchr(obj_syms, Options.tile_show_items[c]);if (!find)continue;object_class_type type = (object_class_type)(find - obj_syms);// First, normal inventoryfor (int i = 0; i < ENDOFPACK; i++){if (!is_valid_item(you.inv[i]) || you.inv[i].quantity == 0)continue;if (you.inv[i].base_type != type)continue;InventoryTile desc;_fill_item_info(desc, you.inv[i]);desc.idx = i;for (int eq = 0; eq < NUM_EQUIP; eq++){if (you.equip[eq] == i){desc.flag |= TILEI_FLAG_EQUIP;break;}}inv.push_back(desc);}}// Finish out this rowwhile (inv.size() % m_region_self_inv->mx != 0){InventoryTile desc;inv.push_back(desc);}// How many ground items do we have?unsigned int num_ground = 0;for (int i = igrd[you.x_pos][you.y_pos]; i != NON_ITEM; i = mitm[i].link)num_ground++;// Add extra rows, if needed.unsigned int ground_rows =std::max(((int)num_ground-1) / (int)m_region_self_inv->mx + 1, 1);while (inv.size() / m_region_self_inv->mx + ground_rows < m_region_self_inv->my){for (unsigned int i = 0; i < m_region_self_inv->mx; i++){InventoryTile desc;inv.push_back(desc);}}// Then, ground items...for (unsigned int c = 0; c < strlen(Options.tile_show_items); c++){if (inv.size() >= m_region_self_inv->mx * m_region_self_inv->my)break;const char *find = strchr(obj_syms, Options.tile_show_items[c]);if (!find)continue;object_class_type type = (object_class_type)(find - obj_syms);for (int i = igrd[you.x_pos][you.y_pos]; i != NON_ITEM; i = mitm[i].link){if (inv.size() >= m_region_self_inv->mx * m_region_self_inv->my)break;if (mitm[i].base_type != type)continue;InventoryTile desc;_fill_item_info(desc, mitm[i]);desc.idx = i;inv.push_back(desc);}}// Finish out ground inventorywhile (inv.size() < m_region_self_inv->mx * m_region_self_inv->my){InventoryTile desc;desc.flag = TILEI_FLAG_FLOOR;inv.push_back(desc);}m_region_self_inv->update(inv.size(), &inv[0]);}void TilesFramework::update_menu_inventory(unsigned int slot,const item_def &item,bool selected, char key){InventoryTile desc;_fill_item_info(desc, item);desc.key = key;desc.idx = (desc.flag & TILEI_FLAG_FLOOR) ? item.index() :letter_to_index(key);if (selected)desc.flag |= TILEI_FLAG_SELECT;m_region_menu_inv->update_slot(slot, desc);}void TilesFramework::place_cursor(cursor_type type, const coord_def &gc){m_region_tile->place_cursor(type, gc);}void TilesFramework::clear_text_tags(text_tag_type type){m_region_tile->clear_text_tags(type);}void TilesFramework::add_text_tag(text_tag_type type, const std::string &tag,const coord_def &gc){m_region_tile->add_text_tag(type, tag, gc);}bool TilesFramework::initialise_items(){return (m_image.load_item_texture());}const coord_def &TilesFramework::get_cursor() const{return (m_region_tile->get_cursor());}
// display dungeon: tileb = { fg(0,0),bg(0,0),fg(1,0),bg(1,0), ..void TileDrawDungeon(unsigned int *tileb);// display memorised dungeonvoid TileDrawFarDungeon(int cx, int cy);// display map centered on grid coordsvoid TileDrawMap(int gx, int gy);void LoadDungeonView(unsigned int *tileb);void StoreDungeonView(unsigned int *tileb);
// display inventryvoid TileDrawInvData(int n, int flag, int *tiles, int *num,int *idx, int *iflags);void TileDrawOneItem(int region, int i, char key, int idx,int tile, int num, bool floor,bool select, bool equip, bool tried, bool cursed);void TileRedrawInv(int region);void TileClearInv(int region);void TileMoveInvCursor(int ix);int TileInvIdx(int i);// refresh player tilevoid TilePlayerRefresh();
#define TILEI_FLAG_SELECT 0x100#define TILEI_FLAG_TRIED 0x200#define TILEI_FLAG_EQUIP 0x400#define TILEI_FLAG_FLOOR 0x800#define TILEI_FLAG_CURSE 0x1000#define TILEI_FLAG_CURSOR 0x2000
enum{TILEI_FLAG_SELECT = 0x0100,TILEI_FLAG_TRIED = 0x0200,TILEI_FLAG_EQUIP = 0x0400,TILEI_FLAG_FLOOR = 0x0800,TILEI_FLAG_CURSE = 0x1000,TILEI_FLAG_CURSOR = 0x2000};
#endif
/** File: tilereg.h* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/#ifdef USE_TILE#ifndef TILEREG_H#define TILEREG_H#include "tiletex.h"#include "tiles.h"#include <vector>class ImageManager{public:ImageManager();virtual ~ImageManager();bool load_textures();bool load_item_texture();void unload_textures();FixedVector<TilesTexture, TEX_MAX> m_textures;};// Windows and internal regions (text, dungeon, map, etc)class MouseEvent;class Region{public:Region();virtual ~Region();void resize(unsigned int mx, unsigned int my);void place(unsigned int sx, unsigned int sy, unsigned int margin);void resize_to_fit(int wx, int wy);// Returns true if the mouse position is over the region// If true, then cx and cy are set in the range [0..mx-1], [0..my-1]virtual bool mouse_pos(int mouse_x, int mouse_y, int &cx, int &cy);bool inside(unsigned int px, unsigned int py);virtual bool update_tip_text(std::string &tip) { return false; }virtual int handle_mouse(MouseEvent &event) = 0;virtual void render() = 0;virtual void clear() = 0;// Geometry// <-----------------wx----------------------->// sx ox ex// |margin| text/tile area |margin|// Offset in pixelsunsigned int ox;unsigned int oy;// Unit sizeunsigned int dx;unsigned int dy;// Region size in dx/dyunsigned int mx;unsigned int my;// Width of the region in pixelsunsigned int wx;unsigned int wy;// Start position in pixels (top left)unsigned int sx;unsigned int sy;// End position in pixels (bottom right)unsigned int ex;unsigned int ey;static coord_def NO_CURSOR;protected:void recalculate();virtual void on_resize() = 0;};class FTFont;class TextRegion : public Region{public:TextRegion(FTFont *font);~TextRegion();virtual void render();virtual void clear();// STATIC -// TODO enne - move these to TilesFramework?// where now printing? what color?static unsigned int print_x;static unsigned int print_y;static int text_col;// which region now printing?static class TextRegion *text_mode;// display cursor? where is the cursor now?static int cursor_flag;static class TextRegion *cursor_region;static unsigned int cursor_x;static unsigned int cursor_y;// class methodsstatic void cgotoxy(int x, int y);static int wherex();static int wherey();//static int get_number_of_lines(void);static void _setcursortype(int curstype);static void textbackground(int bg);static void textcolor(int col);// Object's methodvoid clear_to_end_of_line(void);void putch(unsigned char chr);void writeWChar(unsigned char *ch);unsigned char *cbuf; //text backupunsigned char *abuf; //textcolor backupint cx_ofs; //cursor x offsetint cy_ofs; //cursor y offsetvoid addstr(char *buffer);void addstr_aux(char *buffer, unsigned int len);void adjust_region(int *x1, int *x2, int y);void scroll();//Sys depvoid draw_cursor(int x, int y, int width);void draw_cursor(int x, int y);void erase_cursor();protected:virtual void on_resize();FTFont *m_font;};class StatRegion : public TextRegion{public:StatRegion(FTFont *font);virtual int handle_mouse(MouseEvent &event);virtual bool update_tip_text(std::string &tip);};class MessageRegion : public TextRegion{public:MessageRegion(FTFont *font);virtual int handle_mouse(MouseEvent &event);virtual bool update_tip_text(std::string &tip);};class CRTRegion : public TextRegion{public:CRTRegion(FTFont *font);virtual int handle_mouse(MouseEvent &event);};class TileRegion : public Region{public:TileRegion(ImageManager *im, unsigned int tile_x, unsigned int tile_y);~TileRegion();protected:void add_quad(TextureID tex, unsigned int idx, unsigned int x, unsigned int y, int ofs_x = 0, int ofs_y = 0);ImageManager *m_image;struct tile_vert{float pos_x;float pos_y;float tex_x;float tex_y;};std::vector<tile_vert> m_verts;};struct TextTag{std::string tag;coord_def gc;};enum cursor_type{CURSOR_MOUSE,CURSOR_TUTORIAL,CURSOR_MAX};enum text_tag_type{TAG_NAMED_MONSTER,TAG_TUTORIAL,TAG_MAX};class DungeonRegion : public TileRegion{public:DungeonRegion(ImageManager *im, FTFont *tag_font,unsigned int tile_x, unsigned int tile_y);virtual ~DungeonRegion();virtual void render();virtual void clear();virtual int handle_mouse(MouseEvent &event);virtual bool update_tip_text(std::string &tip);virtual void on_resize();void load_dungeon(unsigned int* tileb, int cx_to_gx, int cy_to_gy);void place_cursor(cursor_type type, const coord_def &gc);bool on_screen(const coord_def &gc) const;void clear_text_tags(text_tag_type type);void add_text_tag(text_tag_type type, const std::string &tag,const coord_def &gc);const coord_def &get_cursor() const { return m_cursor[CURSOR_MOUSE]; }protected:void draw_background(unsigned int bg, unsigned int x, unsigned int y);bool draw_objects(unsigned int fg, unsigned int x, unsigned int y);void draw_player(unsigned int x, unsigned int y);void draw_monster(unsigned int fg, unsigned int x, unsigned int y);void draw_foreground(unsigned int bg, unsigned int fg, unsigned int x, unsigned int y);void draw_doll(dolls_data &doll, unsigned int x, unsigned int y);void draw_draco(int colour, int mon_idx, int equ_tile, unsigned int x, unsigned int y);void add_quad_doll(unsigned int part, unsigned int idx, int ymax, unsigned int x, unsigned int y, int ox, int oy);int get_buffer_index(const coord_def &gc);void to_screen_coords(const coord_def &gc, coord_def& pc) const;std::vector<unsigned int> m_tileb;int m_cx_to_gx;int m_cy_to_gy;coord_def m_cursor[CURSOR_MAX];std::vector<TextTag> m_tags[TAG_MAX];FTFont *m_tag_font;};class InventoryTile{public:InventoryTile();// tile indexint tile;// mitm/you.inv idx (depends on flag & TILEI_FLAG_FLOOR)int idx;// quantity of this item (0-999 valid, >999 shows as 999, <0 shows nothing)short quantity;// bitwise-or of TILEI_FLAG enumerationunsigned short flag;// for inventory items, the slotchar key;bool empty() const;};class InventoryRegion : public TileRegion{public:InventoryRegion(ImageManager *im, unsigned int tile_x, unsigned int tile_y);virtual ~InventoryRegion();virtual void clear();virtual void render();virtual void on_resize();virtual int handle_mouse(MouseEvent &event);void update(unsigned int num, InventoryTile *items);void update_slot(unsigned int slot, InventoryTile &item);virtual bool update_tip_text(std::string &tip);protected:void pack_tile(unsigned int x, unsigned int y, unsigned int idx);void pack_verts();void add_quad_char(char c, unsigned int x, unsigned int y, int ox, int oy);void place_cursor(const coord_def &cursor);unsigned int cursor_index() const;unsigned int m_base_verts;std::vector<InventoryTile> m_items;unsigned char *m_flavour;coord_def m_cursor;bool m_need_to_pack;};enum map_colour{MAP_BLACK,MAP_DKGREY,MAP_MDGREY,MAP_LTGREY,MAP_WHITE,MAP_BLUE,MAP_LTBLUE,MAP_DKBLUE,MAP_GREEN,MAP_LTGREEN,MAP_DKGREEN,MAP_CYAN,MAP_LTCYAN,MAP_DKCYAN,MAP_RED,MAP_LTRED,MAP_DKRED,MAP_MAGENTA,MAP_LTMAGENTA,MAP_DKMAGENTA,MAP_YELLOW,MAP_LTYELLOW,MAP_DKYELLOW,MAP_BROWN,MAX_MAP_COL};class MapRegion : public Region{public:MapRegion(unsigned int pixsz);~MapRegion();virtual void render();virtual void clear();virtual int handle_mouse(MouseEvent &event);virtual bool update_tip_text(std::string &tip);void init_colours();void set(unsigned int gx, unsigned int gy, map_feature f);void set_window(const coord_def &start, const coord_def &end);protected:virtual void on_resize();void update_offsets();map_colour m_colours[MF_MAX];unsigned int m_min_gx, m_max_gx, m_min_gy, m_max_gy;coord_def m_win_start;coord_def m_win_end;unsigned char *m_buf;bool m_far_view;};#endif#endif
/** File: tilereg.cc* Summary: Region system implementaions** Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: j-p-e-g $ on $Date: 2008-03-07 $*/#include "AppHdr.h"#include "cio.h"#include "debug.h"#include "describe.h"#include "food.h"#include "itemname.h"#include "it_use2.h"#include "item_use.h"#include "message.h"#include "misc.h"#include "newgame.h"#include "mon-util.h"#include "player.h"#include "spells3.h"#include "stuff.h"#include "terrain.h"#include "transfor.h"#include "travel.h"#include "tilereg.h"#include "tiles.h"#include "tilefont.h"#include "tilesdl.h"#include "tiledef-dngn.h"#include <SDL_opengl.h>coord_def Region::NO_CURSOR(-1, -1);unsigned int TextRegion::print_x;unsigned int TextRegion::print_y;TextRegion *TextRegion::text_mode = NULL;int TextRegion::text_col = 0;TextRegion *TextRegion::cursor_region= NULL;int TextRegion::cursor_flag = 0;unsigned int TextRegion::cursor_x;unsigned int TextRegion::cursor_y;const int map_colours[MAX_MAP_COL][3] ={{ 0, 0, 0}, // BLACK{128, 128, 128}, // DKGREY{160, 160, 160}, // MDGREY{192, 192, 192}, // LTGREY{255, 255, 255}, // WHITE{ 0, 64, 255}, // BLUE (actually cyan-blue){128, 128, 255}, // LTBLUE{ 0, 32, 128}, // DKBLUE (maybe too dark){ 0, 255, 0}, // GREEN{128, 255, 128}, // LTGREEN{ 0, 128, 0}, // DKGREEN{ 0, 255, 255}, // CYAN{ 64, 255, 255}, // LTCYAN (maybe too pale){ 0, 128, 128}, // DKCYAN{255, 0, 0}, // RED{255, 128, 128}, // LTRED (actually pink){128, 0, 0}, // DKRED{192, 0, 255}, // MAGENTA (actually blue-magenta){255, 128, 255}, // LTMAGENTA{ 96, 0, 128}, // DKMAGENTA{255, 255, 0}, // YELLOW{255, 255, 64}, // LTYELLOW (maybe too pale){128, 128, 0}, // DKYELLOW{165, 91, 0}, // BROWN};const int dir_dx[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};const int dir_dy[9] = {1, 1, 1, 0, 0, 0, -1, -1, -1};const int cmd_normal[9] = {'b', 'j', 'n', 'h', '.', 'l', 'y', 'k', 'u'};const int cmd_shift[9] = {'B', 'J', 'N', 'H', '5', 'L', 'Y', 'K', 'U'};const int cmd_ctrl[9] = {CONTROL('B'), CONTROL('J'), CONTROL('N'),CONTROL('H'), 'X', CONTROL('L'),CONTROL('Y'), CONTROL('K'), CONTROL('U')};const int cmd_dir[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};Region::Region() :ox(0),oy(0),dx(0),dy(0),mx(0),my(0),wx(0),wy(0),sx(0),sy(0),ex(0),ey(0){}void Region::resize(unsigned int _mx, unsigned int _my){mx = _mx;my = _my;recalculate();}void Region::place(unsigned int _sx, unsigned int _sy, unsigned int margin){sx = _sx;sy = _sy;ox = margin;oy = margin;recalculate();}void Region::resize_to_fit(int _wx, int _wy){if (_wx < 0 || _wy < 0){mx = wx = my = wy = 0;ey = sy;ex = sy;return;}unsigned int inner_x = _wx - 2 * ox;unsigned int inner_y = _wy - 2 * oy;mx = dx ? inner_x / dx : 0;my = dy ? inner_y / dy : 0;recalculate();}void Region::recalculate(){wx = ox * 2 + mx * dx;wy = oy * 2 + my * dy;ex = sx + wx;ey = sy + wy;on_resize();}Region::~Region(){}bool Region::inside(unsigned int x, unsigned int y){// TODO enne - need to handle invalid/unintialised regions?return (x >= sx && y >= sy && x <= ex && y <= ey);}bool Region::mouse_pos(int mouse_x, int mouse_y, int &cx, int &cy){int x = mouse_x - ox - sx;int y = mouse_y - oy - sy;bool valid = (x >= 0 && y >= 0);x /= dx;y /= dy;valid &= ((unsigned int)x < mx && (unsigned int)y < my);cx = x;cy = y;return valid;}TileRegion::TileRegion(ImageManager* im, unsigned int tile_x, unsigned int tile_y){ASSERT(im);m_image = im;dx = tile_x;dy = tile_y;}TileRegion::~TileRegion(){}DungeonRegion::DungeonRegion(ImageManager* im, FTFont *tag_font,unsigned int tile_x, unsigned int tile_y) :TileRegion(im, tile_x, tile_y),m_cx_to_gx(0),m_cy_to_gy(0),m_tag_font(tag_font){ASSERT(tag_font);for (unsigned int i = 0; i < CURSOR_MAX; i++)m_cursor[i] = NO_CURSOR;}DungeonRegion::~DungeonRegion(){}void DungeonRegion::load_dungeon(unsigned int* tileb, int cx_to_gx, int cy_to_gy){m_tileb.clear();if (!tileb)return;unsigned int len = 2 * crawl_view.viewsz.x * crawl_view.viewsz.y;m_tileb.resize(len);// TODO enne - move this function into dungeonregiontile_finish_dngn(tileb, you.pos().x, you.pos().y);memcpy(&m_tileb[0], tileb, sizeof(unsigned int) * len);m_cx_to_gx = cx_to_gx;m_cy_to_gy = cy_to_gy;place_cursor(CURSOR_TUTORIAL, m_cursor[CURSOR_TUTORIAL]);}void DungeonRegion::add_quad_doll(unsigned int part, unsigned int idx, int ymax, unsigned int x, unsigned int y, int ox_spec, int oy_spec){float tex_sx, tex_sy, tex_wx, tex_wy;int ox_extra, oy_extra, wx_pix, wy_pix;m_image->m_textures[TEX_DOLL].get_texcoord_doll(part, idx, ymax, tex_sx, tex_sy, tex_wx, tex_wy, wx_pix, wy_pix, ox_extra, oy_extra);if (wx_pix <= 0 || wy_pix <= 0)return;float pos_ox = (ox_spec + ox_extra) / (float)TILE_X;float pos_oy = (oy_spec + oy_extra) / (float)TILE_Y;float tex_ex = tex_sx + tex_wx;float tex_ey = tex_sy + tex_wy;float pos_sx = x + pos_ox;float pos_sy = y + pos_oy;float pos_ex = pos_sx + wx_pix / (float)TILE_X;float pos_ey = pos_sy + wy_pix / (float)TILE_Y;tile_vert v;v.pos_x = pos_sx;v.pos_y = pos_sy;v.tex_x = tex_sx;v.tex_y = tex_sy;m_verts.push_back(v);v.pos_y = pos_ey;v.tex_y = tex_ey;m_verts.push_back(v);v.pos_x = pos_ex;v.tex_x = tex_ex;m_verts.push_back(v);v.pos_y = pos_sy;v.tex_y = tex_sy;m_verts.push_back(v);}void TileRegion::add_quad(TextureID tex, unsigned int idx, unsigned int x, unsigned int y, int ofs_x, int ofs_y){// Generate quad//// 0 - 3// | |// 1 - 2//// Data Layout:// float2 (position)// float2 (texcoord)float tex_sx, tex_sy, tex_wx, tex_wy;m_image->m_textures[tex].get_texcoord(idx, tex_sx, tex_sy, tex_wx, tex_wy);float tex_ex = tex_sx + tex_wx;float tex_ey = tex_sy + tex_wy;float pos_sx = x + ofs_x / (float)TILE_X;float pos_sy = y + ofs_y / (float)TILE_Y;float pos_ex = pos_sx + 1;float pos_ey = pos_sy + 1;// TODO enne - handle wx/wy non-standard sizestile_vert v;v.pos_x = pos_sx;v.pos_y = pos_sy;v.tex_x = tex_sx;v.tex_y = tex_sy;m_verts.push_back(v);v.pos_y = pos_ey;v.tex_y = tex_ey;m_verts.push_back(v);v.pos_x = pos_ex;v.tex_x = tex_ex;m_verts.push_back(v);v.pos_y = pos_sy;v.tex_y = tex_sy;m_verts.push_back(v);}void DungeonRegion::draw_background(unsigned int bg, unsigned int x, unsigned int y){unsigned int bg_idx = bg & TILE_FLAG_MASK;if (bg_idx >= TILE_DNGN_WAX_WALL){tile_flavour &flv = env.tile_flv[x + m_cx_to_gx][y + m_cy_to_gy];add_quad(TEX_DUNGEON, flv.floor, x, y);}if (bg & TILE_FLAG_BLOOD){tile_flavour &flv = env.tile_flv[x + m_cx_to_gx][y + m_cy_to_gy];unsigned int offset = flv.special % tile_DNGN_count[IDX_BLOOD];add_quad(TEX_DUNGEON, TILE_BLOOD + offset, x, y);}add_quad(TEX_DUNGEON, bg_idx, x, y);if (bg & TILE_FLAG_HALO)add_quad(TEX_DUNGEON, TILE_HALO, x, y);if (bg & TILE_FLAG_SANCTUARY && !(bg & TILE_FLAG_UNSEEN))add_quad(TEX_DUNGEON, TILE_SANCTUARY, x, y);// Apply the travel exclusion under the foreground if the cell is// visible. It will be applied later if the cell is unseen.if (bg & TILE_FLAG_EXCL_CTR && !(bg & TILE_FLAG_UNSEEN))add_quad(TEX_DUNGEON, TILE_TRAVEL_EXCLUSION_CENTRE_BG, x, y);else if (bg & TILE_FLAG_TRAV_EXCL && !(bg & TILE_FLAG_UNSEEN))add_quad(TEX_DUNGEON, TILE_TRAVEL_EXCLUSION_BG, x, y);if (bg & TILE_FLAG_RAY)add_quad(TEX_DUNGEON, TILE_RAY_MESH, x, y);}void DungeonRegion::draw_player(unsigned int x, unsigned int y){dolls_data default_doll;dolls_data player_doll;dolls_data result;// TODO enne - store character doll here and get genderfor (int i = 0; i < TILEP_PARTS_TOTAL; i++)player_doll.parts[i] = TILEP_SHOW_EQUIP;int gender = 0;tilep_race_default(you.species, gender, you.experience_level,default_doll.parts);result = player_doll;// TODO enne - make these configurableresult.parts[TILEP_PART_BASE] = default_doll.parts[TILEP_PART_BASE];result.parts[TILEP_PART_DRCHEAD] = default_doll.parts[TILEP_PART_DRCHEAD];result.parts[TILEP_PART_DRCWING] = default_doll.parts[TILEP_PART_DRCWING];bool halo = inside_halo(you.x_pos, you.y_pos);result.parts[TILEP_PART_HALO] = halo ? TILEP_HALO_TSO : 0;if (result.parts[TILEP_PART_HAND1] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_WEAPON];if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)result.parts[TILEP_PART_HAND1] = TILEP_HAND1_BLADEHAND;else if (item == -1)result.parts[TILEP_PART_HAND1] = 0;elseresult.parts[TILEP_PART_HAND1] = tilep_equ_weapon(you.inv[item]);}if (result.parts[TILEP_PART_HAND2] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_SHIELD];if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)result.parts[TILEP_PART_HAND2] = TILEP_HAND2_BLADEHAND;else if (item == -1)result.parts[TILEP_PART_HAND2] = 0;elseresult.parts[TILEP_PART_HAND2] = tilep_equ_shield(you.inv[item]);}if (result.parts[TILEP_PART_BODY] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_BODY_ARMOUR];if (item == -1)result.parts[TILEP_PART_BODY] = 0;elseresult.parts[TILEP_PART_BODY] = tilep_equ_armour(you.inv[item]);}if (result.parts[TILEP_PART_CLOAK] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_CLOAK];if (item == -1)result.parts[TILEP_PART_CLOAK] = 0;elseresult.parts[TILEP_PART_CLOAK] = tilep_equ_cloak(you.inv[item]);}if (result.parts[TILEP_PART_HELM] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_HELMET];if (item != -1){result.parts[TILEP_PART_HELM] = tilep_equ_helm(you.inv[item]);}else if (player_mutation_level(MUT_HORNS) > 0){switch (player_mutation_level(MUT_HORNS)){case 1:result.parts[TILEP_PART_HELM] = TILEP_HELM_HORNS1;break;case 2:result.parts[TILEP_PART_HELM] = TILEP_HELM_HORNS2;break;case 3:result.parts[TILEP_PART_HELM] = TILEP_HELM_HORNS3;break;}}else{result.parts[TILEP_PART_HELM] = 0;}}if (result.parts[TILEP_PART_BOOTS] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_BOOTS];if (item != -1)result.parts[TILEP_PART_BOOTS] = tilep_equ_boots(you.inv[item]);else if (player_mutation_level(MUT_HOOVES))result.parts[TILEP_PART_BOOTS] = TILEP_BOOTS_HOOVES;elseresult.parts[TILEP_PART_BOOTS] = 0;}if (result.parts[TILEP_PART_ARM] == TILEP_SHOW_EQUIP){int item = you.equip[EQ_GLOVES];if (item != -1)result.parts[TILEP_PART_ARM] = tilep_equ_gloves(you.inv[item]);else if (player_mutation_level(MUT_CLAWS) >= 3|| you.species == SP_TROLL || you.species == SP_GHOUL){// There is player_has_claws() but it is not equivalent.// Claws appear if they're big enough to not wear gloves// or on races that have claws.result.parts[TILEP_PART_ARM] = TILEP_ARM_CLAWS;}elseresult.parts[TILEP_PART_ARM] = 0;}draw_doll(result, x, y);}bool DungeonRegion::draw_objects(unsigned int fg, unsigned int x, unsigned int y){unsigned int fg_idx = fg & TILE_FLAG_MASK;// handled elsewhereif (fg_idx == TILE_PLAYER)return false;int equ_tile;int draco;int mon_tile;if (get_mcache_entry(fg_idx, mon_tile, equ_tile, draco)){if (!draco)add_quad(TEX_DEFAULT, get_base_idx_from_mcache(fg_idx), x, y);return true;}else if (fg_idx){add_quad(TEX_DEFAULT, fg_idx, x, y);}return false;}void DungeonRegion::draw_doll(dolls_data &doll, unsigned int x, unsigned int y){int p_order[TILEP_PARTS_TOTAL] ={TILEP_PART_SHADOW,TILEP_PART_HALO,TILEP_PART_DRCWING,TILEP_PART_CLOAK,TILEP_PART_BASE,TILEP_PART_BOOTS,TILEP_PART_LEG,TILEP_PART_BODY,TILEP_PART_ARM,TILEP_PART_HAND1,TILEP_PART_HAND2,TILEP_PART_HAIR,TILEP_PART_BEARD,TILEP_PART_HELM,TILEP_PART_DRCHEAD};int flags[TILEP_PARTS_TOTAL];tilep_calc_flags(doll.parts, flags);// For skirts, boots go under the leg armour. For pants, they go over.if (doll.parts[TILEP_PART_LEG] < TILEP_LEG_SKIRT_OFS){p_order[5] = TILEP_PART_BOOTS;p_order[6] = TILEP_PART_LEG;}for (int i = 0; i < TILEP_PARTS_TOTAL; i++){int p = p_order[i];if (!doll.parts[p])continue;int ymax = TILE_Y;if (flags[p] == TILEP_FLAG_CUT_CENTAUR|| flags[p] == TILEP_FLAG_CUT_NAGA){ymax = 18;}if (doll.parts[p] && p == TILEP_PART_BOOTS&& (doll.parts[p] == TILEP_BOOTS_NAGA_BARDING|| doll.parts[p] == TILEP_BOOTS_CENTAUR_BARDING)){// Special case for barding. They should be in "boots" but because// they're double-wide, they're stored in a different part. We just// intercept it here before drawing.char tile = (doll.parts[p] == TILEP_BOOTS_NAGA_BARDING) ?TILEP_SHADOW_NAGA_BARDING :TILEP_SHADOW_CENTAUR_BARDING;add_quad_doll(TILEP_PART_SHADOW, tile, TILE_Y, x, y, 0, 0);}else{add_quad_doll(p, doll.parts[p], ymax, x, y, 0, 0);}}}void DungeonRegion::draw_draco(int colour, int mon_idx, int equ_tile, unsigned int x, unsigned int y){dolls_data doll;int armour = 0;int armour2 = 0;int weapon = 0;int weapon2 = 0;int arm = 0;for (int i = 0; i < TILEP_PARTS_TOTAL; i++)doll.parts[i] = 0;doll.parts[TILEP_PART_SHADOW] = 1;doll.parts[TILEP_PART_BASE] = TILEP_BASE_DRACONIAN + colour * 2;doll.parts[TILEP_PART_DRCWING] = 1 + colour;doll.parts[TILEP_PART_DRCHEAD] = 1 + colour;switch (mon_idx){case MONS_DRACONIAN_CALLER:weapon = TILEP_HAND1_STAFF_EVIL;weapon2 = TILEP_HAND2_BOOK_YELLOW;armour = TILEP_BODY_ROBE_BROWN;break;case MONS_DRACONIAN_MONK:arm = TILEP_ARM_GLOVE_SHORT_BLUE;armour = TILEP_BODY_KARATE2;break;case MONS_DRACONIAN_ZEALOT:weapon = TILEP_HAND1_MACE;weapon2 = TILEP_HAND2_BOOK_CYAN;armour = TILEP_BODY_MONK_BLUE;break;case MONS_DRACONIAN_SHIFTER:weapon = TILEP_HAND1_STAFF_LARGE;armour = TILEP_BODY_ROBE_CYAN;weapon2 = TILEP_HAND2_BOOK_GREEN;break;case MONS_DRACONIAN_ANNIHILATOR:weapon = TILEP_HAND1_STAFF_RUBY;weapon2 = TILEP_HAND2_FIRE_CYAN;armour = TILEP_BODY_ROBE_GREEN_GOLD;break;case MONS_DRACONIAN_KNIGHT:weapon = equ_tile;weapon2 = TILEP_HAND2_SHIELD_KNIGHT_GRAY;armour = TILEP_BODY_BPLATE_METAL1;armour2 = TILEP_LEG_BELT_GRAY;break;case MONS_DRACONIAN_SCORCHER:weapon = TILEP_HAND1_FIRE_RED;weapon2 = TILEP_HAND2_BOOK_RED;armour = TILEP_BODY_ROBE_RED;break;default:weapon = equ_tile;armour = TILEP_BODY_BELT2;armour2 = TILEP_LEG_LOINCLOTH_RED;break;}doll.parts[TILEP_PART_HAND1] = weapon;doll.parts[TILEP_PART_HAND2] = weapon2;doll.parts[TILEP_PART_BODY] = armour;doll.parts[TILEP_PART_LEG] = armour2;doll.parts[TILEP_PART_ARM] = arm;draw_doll(doll, x, y);}void DungeonRegion::draw_monster(unsigned int fg, unsigned int x, unsigned int y){// Currently, monsters only get displayed weapons (no armour)unsigned int fg_idx = fg & TILE_FLAG_MASK;if (fg_idx < TILE_MCACHE_START)return;int equ_tile;int draco;int mon_tile;if (!get_mcache_entry(fg_idx, mon_tile, equ_tile, draco))return;if (draco == 0){int ofs_x, ofs_y;tile_get_monster_weapon_offset(mon_tile, ofs_x, ofs_y);add_quad_doll(TILEP_PART_HAND1, equ_tile, TILE_Y, x, y, ofs_x, ofs_y);// In some cases, overlay a second weapon tile...if (mon_tile == TILE_MONS_DEEP_ELF_BLADEMASTER){int eq2;switch (equ_tile){case TILEP_HAND1_DAGGER:eq2 = TILEP_HAND2_DAGGER;break;case TILEP_HAND1_SABRE:eq2 = TILEP_HAND2_SABRE;break;default:case TILEP_HAND1_SHORT_SWORD_SLANT:eq2 = TILEP_HAND2_SHORT_SWORD_SLANT;break;};add_quad_doll(TILEP_PART_HAND2, eq2, TILE_Y, x, y, -ofs_x, ofs_y);}}else{int colour;switch (draco){default:case MONS_DRACONIAN: colour = 0; break;case MONS_BLACK_DRACONIAN: colour = 1; break;case MONS_YELLOW_DRACONIAN: colour = 2; break;case MONS_GREEN_DRACONIAN: colour = 4; break;case MONS_MOTTLED_DRACONIAN:colour = 5; break;case MONS_PALE_DRACONIAN: colour = 6; break;case MONS_PURPLE_DRACONIAN: colour = 7; break;case MONS_RED_DRACONIAN: colour = 8; break;case MONS_WHITE_DRACONIAN: colour = 9; break;}draw_draco(colour, mon_tile, equ_tile, x, y);}}void DungeonRegion::draw_foreground(unsigned int bg, unsigned int fg, unsigned int x, unsigned int y){unsigned int fg_idx = fg & TILE_FLAG_MASK;unsigned int bg_idx = bg & TILE_FLAG_MASK;if (fg_idx && !(fg & TILE_FLAG_FLYING)){if (bg_idx >= TILE_DNGN_LAVA && bg_idx <= TILE_DNGN_LAVA + 3){add_quad(TEX_DEFAULT, TILE_MASK_LAVA, x, y);}else if (bg_idx >= TILE_DNGN_SHALLOW_WATER&& bg_idx <= TILE_DNGN_SHALLOW_WATER + 3){add_quad(TEX_DEFAULT, TILE_MASK_SHALLOW_WATER, x, y);}else if (bg_idx >= TILE_DNGN_DEEP_WATER&& bg_idx <= TILE_DNGN_DEEP_WATER + 3){add_quad(TEX_DEFAULT, TILE_MASK_DEEP_WATER, x, y);}}if (fg & TILE_FLAG_NET)add_quad(TEX_DEFAULT, TILE_TRAP_NET, x, y);if (fg & TILE_FLAG_S_UNDER)add_quad(TEX_DEFAULT, TILE_SOMETHING_UNDER, x, y);// Pet markint status_shift = 0;if (fg & TILE_FLAG_PET){add_quad(TEX_DEFAULT, TILE_HEART, x, y);status_shift += 10;}else if ((fg & TILE_FLAG_MAY_STAB) == TILE_FLAG_NEUTRAL){add_quad(TEX_DEFAULT, TILE_NEUTRAL, x, y);status_shift += 8;}else if ((fg & TILE_FLAG_MAY_STAB) == TILE_FLAG_STAB){add_quad(TEX_DEFAULT, TILE_STAB_BRAND, x, y);status_shift += 8;}else if ((fg & TILE_FLAG_MAY_STAB) == TILE_FLAG_MAY_STAB){add_quad(TEX_DEFAULT, TILE_MAY_STAB_BRAND, x, y);status_shift += 5;}if (fg & TILE_FLAG_POISON){add_quad(TEX_DEFAULT, TILE_POISON, x, y, -status_shift, 0);status_shift += 5;}if (fg & TILE_FLAG_ANIM_WEP){add_quad(TEX_DEFAULT, TILE_ANIMATED_WEAPON, x, y);}if (bg & TILE_FLAG_UNSEEN)add_quad(TEX_DEFAULT, TILE_MESH, x, y);if (bg & TILE_FLAG_MM_UNSEEN)add_quad(TEX_DEFAULT, TILE_MAGIC_MAP_MESH, x, y);// Don't let the "new stair" icon cover up any existing icons, but// draw it otherwise.if (bg & TILE_FLAG_NEW_STAIR && status_shift == 0)add_quad(TEX_DEFAULT, TILE_NEW_STAIR, x, y);if (bg & TILE_FLAG_EXCL_CTR && (bg & TILE_FLAG_UNSEEN))add_quad(TEX_DUNGEON, TILE_TRAVEL_EXCLUSION_CENTRE_FG, x, y);else if (bg & TILE_FLAG_TRAV_EXCL && (bg & TILE_FLAG_UNSEEN))add_quad(TEX_DUNGEON, TILE_TRAVEL_EXCLUSION_FG, x, y);// Tutorial cursor takes precedence over other cursors.if (bg & TILE_FLAG_TUT_CURSOR){add_quad(TEX_DEFAULT, TILE_TUTORIAL_CURSOR, x, y);}else if (bg & TILE_FLAG_CURSOR){int type = ((bg & TILE_FLAG_CURSOR) == TILE_FLAG_CURSOR1) ?TILE_CURSOR : TILE_CURSOR2;if ((bg & TILE_FLAG_CURSOR) == TILE_FLAG_CURSOR3)type = TILE_CURSOR3;add_quad(TEX_DEFAULT, type, x, y);}}void DungeonRegion::render(){if (m_tileb.size() == 0)return;glLoadIdentity();glTranslatef(sx + ox, sy + oy, 0);glScalef(dx, dy, 1);m_verts.clear();m_verts.reserve(4 * crawl_view.viewsz.x * crawl_view.viewsz.y);GLState state;state.array_vertex = true;state.array_texcoord = true;state.blend = true;state.texture = true;GLStateManager::set(state);int tile = 0;for (int y = 0; y < crawl_view.viewsz.y; y++)for (int x = 0; x < crawl_view.viewsz.x; x++){unsigned int bg = m_tileb[tile + 1];draw_background(bg, x, y);tile += 2;}ASSERT(m_verts.size() > 0);if (m_verts.size() > 0){m_image->m_textures[TEX_DUNGEON].bind();glVertexPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].tex_x);glDrawArrays(GL_QUADS, 0, m_verts.size());}tile = 0;m_verts.clear();int player_x = -1;int player_y = -1;bool need_doll = false;for (int y = 0; y < crawl_view.viewsz.y; y++)for (int x = 0; x < crawl_view.viewsz.x; x++){unsigned int fg = m_tileb[tile];need_doll |= draw_objects(fg, x, y);if ((fg & TILE_FLAG_MASK) == TILE_PLAYER){player_x = x;player_y = y;}tile += 2;}if (m_verts.size() > 0){m_image->m_textures[TEX_DEFAULT].bind();glVertexPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].tex_x);glDrawArrays(GL_QUADS, 0, m_verts.size());}tile = 0;m_verts.clear();if (player_x != -1)draw_player(player_x, player_y);if (need_doll){for (int y = 0; y < crawl_view.viewsz.y; y++)for (int x = 0; x < crawl_view.viewsz.x; x++){unsigned int fg = m_tileb[tile];draw_monster(fg, x, y);tile += 2;}}if (m_verts.size() > 0){m_image->m_textures[TEX_DOLL].bind();glVertexPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].tex_x);glDrawArrays(GL_QUADS, 0, m_verts.size());}tile = 0;m_verts.clear();for (int y = 0; y < crawl_view.viewsz.y; y++)for (int x = 0; x < crawl_view.viewsz.x; x++){unsigned int fg = m_tileb[tile];unsigned int bg = m_tileb[tile + 1];draw_foreground(bg, fg, x, y);tile += 2;}if (m_verts.size() > 0){m_image->m_textures[TEX_DEFAULT].bind();glVertexPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].tex_x);glDrawArrays(GL_QUADS, 0, m_verts.size());}// Draw text labels// TODO enne - add an option for this// TODO enne - be more intelligent about not covering stuff upfor (unsigned int t = 0; t < TAG_MAX; t++){for (unsigned int i = 0; i < m_tags[t].size(); i++){if (!on_screen(m_tags[t][i].gc))continue;coord_def pc;to_screen_coords(m_tags[t][i].gc, pc);// center this coord, which is at the top left of gc's cellpc.x += dx / 2;const coord_def min_pos(sx, sy);const coord_def max_pos(ex, ey);m_tag_font->render_string(pc.x, pc.y, m_tags[t][i].tag.c_str(),min_pos, max_pos, WHITE, true);}}}void DungeonRegion::clear(){m_tileb.clear();}void DungeonRegion::on_resize(){// TODO enne}int DungeonRegion::handle_mouse(MouseEvent &event){if (mouse_control::current_mode() == MOUSE_MODE_NORMAL|| mouse_control::current_mode() == MOUSE_MODE_MACRO|| mouse_control::current_mode() == MOUSE_MODE_MORE){return 0;}int cx;int cy;if (!inside(event.px, event.py))return 0;bool on_map = mouse_pos(event.px, event.py, cx, cy);const coord_def gc(cx + m_cx_to_gx, cy + m_cy_to_gy);tiles.place_cursor(CURSOR_MOUSE, gc);// TODO enne - can we handle this through tooltips// Destroying the message area is such bad behaviour.// mesclr();// terse_describe_square(gc);if (!on_map)return 0;if (mouse_control::current_mode() == MOUSE_MODE_TARGET|| mouse_control::current_mode() == MOUSE_MODE_TARGET_DIR){if (event.event == MouseEvent::MOVE){return CK_MOUSE_MOVE;}else if (event.event == MouseEvent::PRESS&& event.button == MouseEvent::LEFT && on_screen(gc)){return CK_MOUSE_CLICK;}return 0;}if (event.event != MouseEvent::PRESS)return 0;if (you.pos() == gc){switch (event.button){case MouseEvent::LEFT:if (!(event.mod & MOD_SHIFT))return 'g';switch (grid_stair_direction(grd(gc))){case CMD_GO_DOWNSTAIRS:return ('>');case CMD_GO_UPSTAIRS:return ('<');default:return 0;}case MouseEvent::RIGHT:if (!(event.mod & MOD_SHIFT))return '%'; // Character overview.if (you.religion != GOD_NO_GOD)return '^'; // Religion screen.// fall through...default:return 0;}}// else not on player...if (event.button == MouseEvent::RIGHT){full_describe_square(gc);return CK_MOUSE_CMD;}if (event.button != MouseEvent::LEFT)return 0;// If adjacent, return that key (modified by shift or ctrl, etc...)coord_def dir = gc - you.pos();for (unsigned int i = 0; i < 9; i++){if (dir_dx[i] == dir.x && dir_dy[i] == dir.y){if (event.mod & MOD_SHIFT)return cmd_shift[i];else if (event.mod & MOD_CTRL)return cmd_ctrl[i];elsereturn cmd_normal[i];}}// Otherwise, travel to that grid.if (!in_bounds(gc))return 0;// Activate travel.start_travel(gc.x, gc.y);return CK_MOUSE_CMD;}void DungeonRegion::to_screen_coords(const coord_def &gc, coord_def &pc) const{int cx = gc.x - m_cx_to_gx;int cy = gc.y - m_cy_to_gy;pc.x = sx + ox + cx * dx;pc.y = sy + oy + cy * dy;}bool DungeonRegion::on_screen(const coord_def &gc) const{int x = gc.x - m_cx_to_gx;int y = gc.y - m_cy_to_gy;return (x >= 0 && (unsigned int)x < mx && y >= 0 && (unsigned int)y < my);}// Returns the index into m_tileb for the foreground tile.// This value may not be valid. Check on_screen() first.// Add one to the return value to get the background tile idx.int DungeonRegion::get_buffer_index(const coord_def &gc){int x = gc.x - m_cx_to_gx;int y = gc.y - m_cy_to_gy;return 2 * (x + y * mx);}void DungeonRegion::place_cursor(cursor_type type, const coord_def &gc){unsigned int unmask = ~((type == CURSOR_MOUSE) ? TILE_FLAG_CURSOR :TILE_FLAG_TUT_CURSOR);unsigned int mask = (type == CURSOR_MOUSE) ? TILE_FLAG_CURSOR1 :TILE_FLAG_TUT_CURSOR;// Remove cursor from previous locationif (on_screen(m_cursor[type])){unsigned int idx = get_buffer_index(m_cursor[type]) + 1;m_tileb[idx] &= unmask;}// If we're only looking for a direction, put the mouse// cursor next to the player to let them know that their// spell/wand will only go one square.if (mouse_control::current_mode() == MOUSE_MODE_TARGET_DIR&& type == CURSOR_MOUSE){coord_def delta = gc - you.pos();int ax = abs(delta.x);int ay = abs(delta.y);coord_def result = you.pos();if (1000 * ay < 414 * ax)result += (delta.x > 0) ? coord_def(1, 0) : coord_def(-1, 0);else if (1000 * ax < 414 * ay)result += (delta.y > 0) ? coord_def(0, 1) : coord_def(0, -1);else if (delta.x > 0)result += (delta.y > 0) ? coord_def(1, 1) : coord_def(1, -1);else if (delta.x < 0)result += (delta.y > 0) ? coord_def(-1, 1) : coord_def(-1, -1);m_cursor[type] = result;}else{m_cursor[type] = gc;}// Add cursor to new locationif ((m_cursor[type] != NO_CURSOR) && on_screen(m_cursor[type])){unsigned int idx = get_buffer_index(m_cursor[type]) + 1;m_tileb[idx] &= unmask;// TODO enne - specify type of cursor in place_cursor? or determine type based on grd?m_tileb[idx] |= mask;}}bool DungeonRegion::update_tip_text(std::string& tip){// TODO enne - it would be really nice to use the tutorial// descriptions here for features, monsters, etc...// Unfortunately, that would require quite a bit of rewriting// and some parsing of formatting to get that to work.if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return false;if (m_cursor[CURSOR_MOUSE] == you.pos()){tip = you.your_name;tip += " (";tip += get_species_abbrev(you.species);tip += get_class_abbrev(you.char_class);tip += ")";if (igrd(m_cursor[CURSOR_MOUSE]) != NON_ITEM)tip += "\n[L-Click] Pick up items (g)";if (grid_stair_direction(grd(m_cursor[CURSOR_MOUSE])) != CMD_NO_CMD)tip += "\n[Shift-L-Click] use stairs (</>)";// Character overview.tip += "\n[R-Click] Overview (%)";// Religion.if (you.religion != GOD_NO_GOD)tip += "\n[Shift-R-Click] Religion (^)";}else if (abs(m_cursor[CURSOR_MOUSE].x - you.pos().x) <= 1&& abs(m_cursor[CURSOR_MOUSE].y - you.pos().y) <= 1){tip = "";if (!grid_is_solid(m_cursor[CURSOR_MOUSE])){int mon_num = mgrd(m_cursor[CURSOR_MOUSE]);const monsters *mons = &menv[mon_num];if (mon_num == NON_MONSTER || mons_friendly(mons)){tip = "[L-Click] Move\n";}else if (mon_num != NON_MONSTER){tip = mons->name(DESC_CAP_A);tip += "\n[L-Click] Attack\n";}}tip += "[R-Click] Describe";}else{if (i_feel_safe() && !grid_is_solid(m_cursor[CURSOR_MOUSE])){tip = "[L-Click] Travel\n";}tip += "[R-Click] Describe";}return true;}void DungeonRegion::clear_text_tags(text_tag_type type){m_tags[type].clear();}void DungeonRegion::add_text_tag(text_tag_type type, const std::string &tag,const coord_def &gc){TextTag t;t.tag = tag;t.gc = gc;m_tags[type].push_back(t);}InventoryTile::InventoryTile(){tile = 0;idx = -1;quantity = -1;key = 0;flag = 0;}bool InventoryTile::empty() const{return (idx == -1);}InventoryRegion::InventoryRegion(ImageManager* im, unsigned tile_x, unsigned int tile_y) :TileRegion(im, tile_x, tile_y),m_flavour(NULL), m_cursor(NO_CURSOR), m_need_to_pack(false){}InventoryRegion::~InventoryRegion(){delete[] m_flavour;}void InventoryRegion::clear(){m_items.clear();m_verts.clear();}void InventoryRegion::on_resize(){delete[] m_flavour;if (mx * my <= 0)return;m_flavour = new unsigned char[mx * my];for (unsigned int i = 0; i < mx * my; i++){m_flavour[i] = random2((unsigned char)~0);}}void InventoryRegion::update(unsigned int num, InventoryTile *items){m_items.clear();for (unsigned int i = 0; i < num; i++){m_items.push_back(items[i]);}m_need_to_pack = true;}void InventoryRegion::update_slot(unsigned int slot, InventoryTile &desc){while (m_items.size() <= slot){InventoryTile temp;m_items.push_back(temp);}m_items[slot] = desc;m_need_to_pack = true;}void InventoryRegion::render(){if (m_need_to_pack)pack_verts();if (m_verts.size() == 0)return;glLoadIdentity();glTranslatef(sx + ox, sy + oy, 0);glScalef(dx, dy, 1);GLState state;state.array_vertex = true;state.array_texcoord = true;state.blend = true;state.texture = true;GLStateManager::set(state);m_image->m_textures[TEX_DUNGEON].bind();glVertexPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(tile_vert), &m_verts[0].tex_x);glDrawArrays(GL_QUADS, 0, m_base_verts);m_image->m_textures[TEX_DEFAULT].bind();glDrawArrays(GL_QUADS, m_base_verts, m_verts.size() - m_base_verts);}void InventoryRegion::add_quad_char(char c, unsigned int x, unsigned int y, int ofs_x, int ofs_y){int idx = TILE_CHAR00 + (c - 32) / 8;int subidx = c & 7;float tex_sx, tex_sy, tex_wx, tex_wy;m_image->m_textures[TEX_DEFAULT].get_texcoord(idx, tex_sx, tex_sy, tex_wx, tex_wy);tex_wx /= 4.0f;tex_wy /= 2.0f;tex_sx += (subidx % 4) * tex_wx;tex_sy += (subidx / 4) * tex_wy;float tex_ex = tex_sx + tex_wx;float tex_ey = tex_sy + tex_wy;float pos_sx = x + ofs_x / (float)TILE_X;float pos_sy = y + ofs_y / (float)TILE_Y;float pos_ex = pos_sx + 0.25f;float pos_ey = pos_sy + 0.5f;tile_vert v;v.pos_x = pos_sx;v.pos_y = pos_sy;v.tex_x = tex_sx;v.tex_y = tex_sy;m_verts.push_back(v);v.pos_y = pos_ey;v.tex_y = tex_ey;m_verts.push_back(v);v.pos_x = pos_ex;v.tex_x = tex_ex;m_verts.push_back(v);v.pos_y = pos_sy;v.tex_y = tex_sy;m_verts.push_back(v);}void InventoryRegion::pack_verts(){m_need_to_pack = false;m_verts.clear();// ensure the cursor has been placedplace_cursor(m_cursor);// Pack base separately, as it comes from a different texture...unsigned int i = 0;for (unsigned int y = 0; y < my; y++){if (i >= m_items.size())break;for (unsigned int x = 0; x < mx; x++){if (i >= m_items.size())break;InventoryTile &item = m_items[i++];if (item.flag & TILEI_FLAG_FLOOR)add_quad(TEX_DUNGEON, get_floor_tile_idx()+ m_flavour[i] % get_num_floor_flavors(), x, y);elseadd_quad(TEX_DUNGEON, TILE_ITEM_SLOT, x, y);}}// Make note of how many verts are used by the basem_base_verts = m_verts.size();i = 0;for (unsigned int y = 0; y < my; y++){if (i >= m_items.size())break;for (unsigned int x = 0; x < mx; x++){if (i >= m_items.size())break;InventoryTile &item = m_items[i++];if (item.flag & TILEI_FLAG_EQUIP){if (item.flag & TILEI_FLAG_CURSE)add_quad(TEX_DEFAULT, TILE_ITEM_SLOT_EQUIP_CURSED, x, y);elseadd_quad(TEX_DEFAULT, TILE_ITEM_SLOT_EQUIP, x, y);}else if (item.flag & TILEI_FLAG_CURSE)add_quad(TEX_DEFAULT, TILE_ITEM_SLOT_CURSED, x, y);// TODO enne - need better graphic hereif (item.flag & TILEI_FLAG_SELECT)add_quad(TEX_DEFAULT, TILE_ITEM_SLOT_SELECTED, x, y);if (item.flag & TILEI_FLAG_CURSOR)add_quad(TEX_DEFAULT, TILE_CURSOR, x, y);if (item.tile)add_quad(TEX_DEFAULT, item.tile, x, y);if (item.quantity != -1){unsigned int num = item.quantity;// If you have that many, who cares.if (num > 999)num = 999;const int offset_amount = TILE_X/4;int offset = 0;int help = num;int c100 = help/100;help -= c100*100;if (c100){add_quad_char('0' + c100, x, y, offset, 0);offset += offset_amount;}int c10 = help/10;if (c10 || c100){add_quad_char('0' + c10, x, y, offset, 0);offset += offset_amount;}int c1 = help % 10;add_quad_char('0' + c1, x, y, offset, 0);}if (item.flag & TILEI_FLAG_TRIED)add_quad_char('?', x, y, 0, TILE_Y / 2);}}}unsigned int InventoryRegion::cursor_index() const{ASSERT(m_cursor != NO_CURSOR);return m_cursor.x + m_cursor.y * mx;}void InventoryRegion::place_cursor(const coord_def &cursor){if (m_cursor != NO_CURSOR){m_items[cursor_index()].flag &= ~TILEI_FLAG_CURSOR;m_need_to_pack = true;}m_cursor = cursor;if (m_cursor == NO_CURSOR || cursor_index() >= m_items.size())return;// Add cursor to new locationm_items[cursor_index()].flag |= TILEI_FLAG_CURSOR;m_need_to_pack = true;}int InventoryRegion::handle_mouse(MouseEvent &event){int cx, cy;if (!mouse_pos(event.px, event.py, cx, cy)){place_cursor(NO_CURSOR);return 0;}const coord_def cursor(cx, cy);place_cursor(cursor);if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return 0;if (event.event != MouseEvent::PRESS)return 0;// TODO enne - if mouse_mode is command, then:unsigned int item_idx = cursor_index();if (item_idx >= m_items.size() || m_items[item_idx].empty())return 0;int idx = m_items[item_idx].idx;bool on_floor = m_items[item_idx].flag & TILEI_FLAG_FLOOR;ASSERT(idx >= 0);// TODO enne - this is all really only valid for the on-screen inventory// Do we subclass inventoryregion for the onscreen and offscreen versions?char key = m_items[item_idx].key;if (key)return key;if (event.button == MouseEvent::LEFT){if (on_floor){if (event.mod & MOD_SHIFT)tile_item_use_floor(idx);elsetile_item_pickup(idx);}else{if (event.mod & MOD_SHIFT)tile_item_drop(idx);else if (event.mod & MOD_CTRL)tile_item_use_secondary(idx);elsetile_item_use(idx);}// TODO enne - need to redraw inventory here?return CK_MOUSE_CMD;}else if (event.button == MouseEvent::RIGHT){if (on_floor){if (event.mod & MOD_SHIFT)tile_item_eat_floor(idx);elsedescribe_item(mitm[idx]);}else{describe_item(you.inv[idx]);}return CK_MOUSE_CMD;}return 0;}// NOTE: Assumes the item is equipped in the first place!static bool _is_true_equipped_item(item_def item){// Weapons and staves are only truly equipped if wielded.if (item.link == you.equip[EQ_WEAPON])return (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES);// Cursed armour and rings are only truly equipped if *not* wielded.return (item.link != you.equip[EQ_WEAPON]);}// Returns whether there's any action you can take with an item in inventory// apart from dropping it.static bool _can_use_item(const item_def &item, bool equipped){// Vampires can drain corpses.if (item.base_type == OBJ_CORPSES){return (you.species == SP_VAMPIRE&& item.sub_type != CORPSE_SKELETON&& !food_is_rotten(item)&& mons_has_blood(item.plus));}if (equipped && item_cursed(item)){// Misc. items/rods can always be evoked, cursed or not.if (item.base_type == OBJ_MISCELLANY || item_is_rod(item))return true;// You can't unwield/fire a wielded cursed weapon/staff// but cursed armour and rings can be unwielded without problems.return (!_is_true_equipped_item(item));}// Mummies can't do anything with food or potions.if (you.species == SP_MUMMY)return (item.base_type != OBJ_POTIONS && item.base_type != OBJ_FOOD);// In all other cases you can use the item in some way.return true;}bool InventoryRegion::update_tip_text(std::string& tip){unsigned int item_idx = cursor_index();if (item_idx >= m_items.size() || m_items[item_idx].empty())return false;int idx = m_items[item_idx].idx;// TODO enne - consider subclassing this class, rather than depending// on "key" to determine if this is the crt inventory or the on screen one.bool display_actions = (m_items[item_idx].key == 0&& mouse_control::current_mode() == MOUSE_MODE_COMMAND);// TODO enne - should the command keys here respect keymaps?if (m_items[item_idx].flag & TILEI_FLAG_FLOOR){const item_def &item = mitm[idx];tip = "";if (m_items[item_idx].key){tip = m_items[item_idx].key;tip += " - ";}tip += item.name(DESC_NOCAP_A);if (!display_actions)return true;tip += "\n[L-Click] Pick up (g)";if (item.base_type == OBJ_CORPSES&& item.sub_type != CORPSE_SKELETON&& !food_is_rotten(item)){tip += "\n[Shift-L-Click] ";if (can_bottle_blood_from_corpse(item.plus))tip += "Bottle blood";elsetip += "Chop up";tip += " (c)";if (you.species == SP_VAMPIRE)tip += "\n\n[Shift-R-Click] Drink blood (e)";}else if (item.base_type == OBJ_FOOD&& you.is_undead != US_UNDEAD&& you.species != SP_VAMPIRE){tip += "\n[Shift-R-Click] Eat (e)";}}else{const item_def &item = you.inv[idx];tip = item.name(DESC_INVENTORY_EQUIP);if (!display_actions)return true;int type = item.base_type;const bool equipped = m_items[item_idx].flag & TILEI_FLAG_EQUIP;bool wielded = (you.equip[EQ_WEAPON] == idx);const int EQUIP_OFFSET = NUM_OBJECT_CLASSES;if (_can_use_item(item, equipped)){tip += "\n[L-Click] ";if (equipped){if (wielded && type != OBJ_MISCELLANY && !item_is_rod(item)){if (type == OBJ_JEWELLERY || type == OBJ_ARMOUR|| type == OBJ_WEAPONS || type == OBJ_STAVES){type = OBJ_WEAPONS + EQUIP_OFFSET;}}elsetype += EQUIP_OFFSET;}switch (type){// first equipable categoriescase OBJ_WEAPONS:case OBJ_STAVES:case OBJ_MISCELLANY:tip += "Wield (w)";if (is_throwable(item, player_size(PSIZE_BODY)))tip += "\n[Ctrl-L-Click] Fire (f)";break;case OBJ_WEAPONS + EQUIP_OFFSET:tip += "Unwield";if (is_throwable(item, player_size(PSIZE_BODY)))tip += "\n[Ctrl-L-Click] Fire (f)";break;case OBJ_MISCELLANY + EQUIP_OFFSET:if (item.sub_type >= MISC_DECK_OF_ESCAPE&& item.sub_type <= MISC_DECK_OF_DEFENCE){tip += "Draw a card (v)";tip += "\n[Ctrl-L-Click] Unwield";break;}// else fall-throughcase OBJ_STAVES + EQUIP_OFFSET: // rods - other staves handled abovetip += "Evoke (v)";tip += "\n[Ctrl-L-Click] Unwield";break;case OBJ_ARMOUR:tip += "Wear (W)";break;case OBJ_ARMOUR + EQUIP_OFFSET:tip += "Take off (T)";break;case OBJ_JEWELLERY:tip += "Put on (P)";break;case OBJ_JEWELLERY + EQUIP_OFFSET:tip += "Remove (R)";break;case OBJ_MISSILES:tip += "Fire (f)";if (wielded)tip += "\n[Ctrl-L-Click] Unwield";else if ( item.sub_type == MI_STONE&& player_knows_spell(SPELL_SANDBLAST)|| item.sub_type == MI_ARROW&& player_knows_spell(SPELL_STICKS_TO_SNAKES) ){// For Sandblast and Sticks to Snakes,// respectively.tip += "\n[Ctrl-L-Click] Wield (w)";}break;case OBJ_WANDS:tip += "Zap (Z)";if (wielded)tip += "\n[Ctrl-L-Click] Unwield";break;case OBJ_BOOKS:if (item_type_known(item)&& item.sub_type != BOOK_MANUAL&& item.sub_type != BOOK_DESTRUCTION){tip += "Memorise (M)";if (wielded)tip += "\n[Ctrl-L-Click] Unwield";break;}// else fall-throughcase OBJ_SCROLLS:tip += "Read (r)";if (wielded)tip += "\n[Ctrl-L-Click] Unwield";break;case OBJ_POTIONS:tip += "Quaff (q)";// For Sublimation of Blood.if (wielded)tip += "\n[Ctrl-L-Click] Unwield";else if ( item_type_known(item)&& is_blood_potion(item)&& player_knows_spell(SPELL_SUBLIMATION_OF_BLOOD) ){tip += "\n[Ctrl-L-Click] Wield (w)";}break;case OBJ_FOOD:tip += "Eat (e)";// For Sublimation of Blood.if (wielded)tip += "\n[Ctrl-L-Click] Unwield";else if (item.sub_type == FOOD_CHUNK&& player_knows_spell(SPELL_SUBLIMATION_OF_BLOOD)){tip += "\n[Ctrl-L-Click] Wield (w)";}break;case OBJ_CORPSES:if (you.species == SP_VAMPIRE)tip += "Drink blood (e)";if (wielded){if (you.species == SP_VAMPIRE)tip += EOL;tip += "[Ctrl-L-Click] Unwield";}break;default:tip += "Use";}}// For Boneshards.// Special handling since skeletons have no primary action.if (item.base_type == OBJ_CORPSES&& item.sub_type == CORPSE_SKELETON){if (wielded)tip += "\n[Ctrl-L-Click] Unwield";else if (player_knows_spell(SPELL_BONE_SHARDS))tip += "\n[Ctrl-L-Click] Wield (w)";}tip += "\n[R-Click] Info";// Has to be non-equipped or non-cursed to drop.if (!equipped || !_is_true_equipped_item(you.inv[idx])|| !item_cursed(you.inv[idx])){tip += "\n[Shift-L-Click] Drop (d)";}}return true;}MapRegion::MapRegion(unsigned int pixsz) :m_buf(NULL),m_far_view(false){dx = pixsz;dy = pixsz;clear();init_colours();}void MapRegion::on_resize(){delete[] m_buf;int size = mx * my;m_buf = new unsigned char[size];memset(m_buf, 0, sizeof(unsigned char) * size);}void MapRegion::init_colours(){// TODO enne - the options array for colours should be// tied to the map feature enumeration to avoid this function.m_colours[MF_UNSEEN] = (map_colour)Options.tile_unseen_col;m_colours[MF_FLOOR] = (map_colour)Options.tile_floor_col;m_colours[MF_WALL] = (map_colour)Options.tile_wall_col;m_colours[MF_MAP_FLOOR] = (map_colour)Options.tile_floor_col; // TODO ennem_colours[MF_MAP_WALL] = (map_colour)Options.tile_mapped_wall_col;m_colours[MF_DOOR] = (map_colour)Options.tile_door_col;m_colours[MF_ITEM] = (map_colour)Options.tile_item_col;m_colours[MF_MONS_HOSTILE] = (map_colour)Options.tile_monster_col;m_colours[MF_MONS_FRIENDLY] = (map_colour)Options.tile_friendly_col;m_colours[MF_MONS_NEUTRAL] = (map_colour)Options.tile_neutral_col;m_colours[MF_MONS_NO_EXP] = (map_colour)Options.tile_plant_col;m_colours[MF_STAIR_UP] = (map_colour)Options.tile_upstairs_col;m_colours[MF_STAIR_DOWN] = (map_colour)Options.tile_downstairs_col;m_colours[MF_STAIR_BRANCH] = (map_colour)Options.tile_feature_col;m_colours[MF_FEATURE] = (map_colour)Options.tile_feature_col;m_colours[MF_WATER] = (map_colour)Options.tile_water_col;m_colours[MF_LAVA] = (map_colour)Options.tile_lava_col;m_colours[MF_TRAP] = (map_colour)Options.tile_trap_col;m_colours[MF_EXCL_ROOT] = (map_colour)Options.tile_excl_centre_col;m_colours[MF_EXCL] = (map_colour)Options.tile_excluded_col;m_colours[MF_PLAYER] = (map_colour)Options.tile_player_col;}MapRegion::~MapRegion(){delete[] m_buf;}struct map_vertex{float x;float y;unsigned char r;unsigned char g;unsigned char b;unsigned char a;};void MapRegion::render(){if (m_min_gx > m_max_gx || m_min_gy > m_max_gy)return;// [enne] - GL_POINTS should probably be used here, but there's (apparently)// a bug in the OpenGL driver that I'm using and it doesn't respect// glPointSize unless GL_SMOOTH_POINTS is on. GL_SMOOTH_POINTS is// *terrible* for performance if it has to fall back on software rendering,// so instead we'll just make quads.glLoadIdentity();glTranslatef(sx + ox, sy + oy, 0);glScalef(dx, dx, 1);std::vector<map_vertex> verts;verts.reserve(4 * (m_max_gx - m_min_gx + 1) * (m_max_gy - m_min_gy + 1));for (unsigned int x = m_min_gx; x <= m_max_gx; x++){for (unsigned int y = m_min_gy; y <= m_max_gy; y++){map_feature f = (map_feature)m_buf[x + y * mx];map_colour c = m_colours[f];unsigned int pos_x = x - m_min_gx;unsigned int pos_y = y - m_min_gy;map_vertex v;v.r = map_colours[c][0];v.g = map_colours[c][1];v.b = map_colours[c][2];v.a = 255;v.x = pos_x;v.y = pos_y;verts.push_back(v);v.x = pos_x;v.y = pos_y + 1;verts.push_back(v);v.x = pos_x + 1;v.y = pos_y + 1;verts.push_back(v);v.x = pos_x + 1;v.y = pos_y;verts.push_back(v);}}GLState state;state.array_vertex = true;state.array_colour = true;GLStateManager::set(state);glVertexPointer(2, GL_FLOAT, sizeof(map_vertex), &verts[0].x);glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(map_vertex), &verts[0].r);glDrawArrays(GL_QUADS, 0, verts.size());// TODO enne - make sure we're drawing within the map square here...// Draw window box.if (m_win_start.x == -1 && m_win_end.x == -1)return;verts.clear();glLoadIdentity();glTranslatef(sx + ox, sy + oy, 0);map_vertex v;int c = (int)Options.tile_window_col;v.r = map_colours[c][0];v.g = map_colours[c][1];v.b = map_colours[c][2];v.a = 255;v.x = (int)dx * (m_win_start.x - (int)m_min_gx);v.y = (int)dy * (m_win_start.y - (int)m_min_gy);verts.push_back(v);v.y = (int)dy * (m_win_end.y - (int)m_min_gy) + 1;verts.push_back(v);v.x = (int)dx * (m_win_end.x - (int)m_min_gx) + 1;verts.push_back(v);v.y = (int)dy * (m_win_start.y - (int)m_min_gy);verts.push_back(v);glVertexPointer(2, GL_FLOAT, sizeof(map_vertex), &verts[0].x);glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(map_vertex), &verts[0].r);glDrawArrays(GL_LINE_LOOP, 0, verts.size());}void MapRegion::update_offsets(){// adjust offsets to center mapox = (wx - dx * (m_max_gx - m_min_gx)) / 2;oy = (wy - dy * (m_max_gy - m_min_gy)) / 2;}void MapRegion::set(unsigned int gx, unsigned int gy, map_feature f){ASSERT((unsigned int)f <= (unsigned char)~0);m_buf[gx + gy * mx] = f;if (f == MF_UNSEEN)return;// Get map extentsm_min_gx = std::min(m_min_gx, gx);m_max_gx = std::max(m_max_gx, gx);m_min_gy = std::min(m_min_gy, gy);m_max_gy = std::max(m_max_gy, gy);update_offsets();}void MapRegion::set_window(const coord_def &start, const coord_def &end){m_win_start = start;m_win_end = end;}void MapRegion::clear(){m_min_gx = GXM;m_max_gx = 0;m_min_gy = GYM;m_max_gy = 0;m_win_start.x = -1;m_win_start.y = -1;m_win_end.x = -1;m_win_end.y = -1;update_offsets();if (m_buf)memset(m_buf, 0, sizeof(*m_buf) * mx * my);}int MapRegion::handle_mouse(MouseEvent &event){if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return 0;int cx;int cy;if (!mouse_pos(event.px, event.py, cx, cy)){if (m_far_view){m_far_view = false;tiles.load_dungeon(you.pos().x, you.pos().y);return 0;}return 0;}const coord_def gc(m_min_gx + cx, m_min_gy + cy);tiles.place_cursor(CURSOR_MOUSE, gc);switch (event.event){case MouseEvent::MOVE:if (m_far_view)tiles.load_dungeon(gc.x, gc.y);return 0;case MouseEvent::PRESS:if (event.button == MouseEvent::LEFT){if (!in_bounds(gc))return 0;start_travel(gc.x, gc.y);}else if (event.button == MouseEvent::RIGHT){m_far_view = true;tiles.load_dungeon(gc.x, gc.y);}return CK_MOUSE_CMD;case MouseEvent::RELEASE:if ((event.button == MouseEvent::RIGHT) && m_far_view){tiles.load_dungeon(you.pos().x, you.pos().y);}return 0;default:return 0;}}bool MapRegion::update_tip_text(std::string& tip){if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return false;tip = "[L-Click] Travel / [R-Click] View";return true;}void TextRegion::scroll(){for (unsigned int idx = 0; idx < mx*(my-1); idx++){cbuf[idx] = cbuf[idx + mx];abuf[idx] = abuf[idx + mx];}for (unsigned int idx = mx*(my-1); idx < mx*my; idx++){cbuf[idx] = ' ';abuf[idx] = 0;}if (print_y > 0)print_y -= 1;if (cursor_y > 0)cursor_y -= 1;}TextRegion::TextRegion(FTFont *font) :cbuf(NULL),abuf(NULL),cx_ofs(0),cy_ofs(0),m_font(font){ASSERT(font);dx = m_font->char_width();dy = m_font->char_height();// TODO enne - gah!dx = 8;}void TextRegion::on_resize(){delete cbuf;delete abuf;unsigned int size = mx * my;cbuf = new unsigned char[size];abuf = new unsigned char[size];for (unsigned int i = 0; i < size; i++){cbuf[i] = ' ';abuf[i] = 0;}}TextRegion::~TextRegion(){delete[] cbuf;delete[] abuf;}void TextRegion::adjust_region(int *x1, int *x2, int y){*x2 = *x2 + 1;}void TextRegion::addstr(char *buffer){char buf2[1024];int len = strlen(buffer);int j = 0;for (int i = 0; i < len + 1; i++){char c = buffer[i];bool newline = false;if (c == '\n' || c == '\r'){c = 0;newline = true;if (buffer[i+1] == '\n' || buffer[i+1] == '\r')i++;}buf2[j] = c;j++;if (c == 0){if (j-1 != 0)addstr_aux(buf2, j - 1); // draw itif (newline){print_x = cx_ofs;print_y++;j = 0;if (print_y - cy_ofs == my)scroll();}}}if (cursor_flag)cgotoxy(print_x+1, print_y+1);}void TextRegion::addstr_aux(char *buffer, unsigned int len){int x = print_x - cx_ofs;int y = print_y - cy_ofs;int adrs = y * mx;int head = x;int tail = x + len - 1;adjust_region(&head, &tail, y);for (unsigned int i = 0; i < len && x + i < mx; i++){cbuf[adrs+x+i] = buffer[i];abuf[adrs+x+i] = text_col;}print_x += len;}void TextRegion::clear_to_end_of_line(){int cx = print_x - cx_ofs;int cy = print_y - cy_ofs;int col = text_col;int adrs = cy * mx;ASSERT(adrs + mx - 1 < mx * my);for (unsigned int i = cx; i < mx; i++){cbuf[adrs+i] = ' ';abuf[adrs+i] = col;}}void TextRegion::putch(unsigned char ch){if (ch == 0)ch=32;addstr_aux((char *)&ch, 1);}void TextRegion::writeWChar(unsigned char *ch){addstr_aux((char *)ch, 2);}void TextRegion::textcolor(int color){text_col = color;}void TextRegion::textbackground(int col){textcolor(col*16 + (text_col & 0xf));}void TextRegion::cgotoxy(int x, int y){ASSERT(x >= 1);ASSERT(y >= 1);print_x = x-1;print_y = y-1;if (cursor_region != NULL && cursor_flag){cursor_region ->erase_cursor();cursor_region = NULL;}if (cursor_flag){text_mode->draw_cursor(print_x, print_y);cursor_x = print_x;cursor_y = print_y;cursor_region = text_mode;}}int TextRegion::wherex(){return print_x + 1;}int TextRegion::wherey(){return print_y + 1;}void TextRegion::_setcursortype(int curstype){cursor_flag = curstype;if (cursor_region != NULL)cursor_region->erase_cursor();if (curstype){text_mode->draw_cursor(print_x, print_y);cursor_x = print_x;cursor_y = print_y;cursor_region = text_mode;}}void TextRegion::draw_cursor(int x, int y){// TODO enne}void TextRegion::erase_cursor(){// TODO enne}void TextRegion::render(){m_font->render_textblock(sx + ox, sy + oy, cbuf, abuf, mx, my);}void TextRegion::clear(){for (unsigned int i = 0; i < mx * my; i++){cbuf[i] = ' ';abuf[i] = 0;}}StatRegion::StatRegion(FTFont *font) : TextRegion(font){}int StatRegion::handle_mouse(MouseEvent &event){if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return 0;if (!inside(event.px, event.py))return 0;if (event.event != MouseEvent::PRESS || event.button != MouseEvent::LEFT)return 0;// Restingreturn '5';}bool StatRegion::update_tip_text(std::string& tip){if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return false;tip = "[L-Click] Rest / Search for a while";return true;}MessageRegion::MessageRegion(FTFont *font) : TextRegion(font){}int MessageRegion::handle_mouse(MouseEvent &event){// TODO enne - mouse scrolling here should mouse scroll up through// the message history in the message pane, without going to the CRT.if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return 0;if (!inside(event.px, event.py))return 0;if (event.event != MouseEvent::PRESS || event.button != MouseEvent::LEFT)return 0;return CONTROL('P');}bool MessageRegion::update_tip_text(std::string& tip){if (mouse_control::current_mode() != MOUSE_MODE_COMMAND)return false;tip = "[L-Click] Browse message history";return true;}CRTRegion::CRTRegion(FTFont *font) : TextRegion(font){}int CRTRegion::handle_mouse(MouseEvent &event){// TODO enne - clicking on menu items? We could probably// determine which items were clicked based on text size.return 0;}ImageManager::ImageManager(){}ImageManager::~ImageManager(){unload_textures();}bool ImageManager::load_textures(){GenericTexture::MipMapOptions mip = GenericTexture::MIPMAP_CREATE;if (!m_textures[TEX_DUNGEON].load_texture("dngn.png", mip))return false;if (!m_textures[TEX_DOLL].load_texture("player.png", mip))return false;if (!m_textures[TEX_TITLE].load_texture("title.png", mip))return false;return true;}static void _copy_onto(unsigned char *pixels, unsigned int width,unsigned int height, unsigned char *src,int idx, bool blend){const unsigned int tile_size = 32;const unsigned int tiles_per_row = width / tile_size;unsigned int row = idx / tiles_per_row;unsigned int col = idx % tiles_per_row;unsigned char *dest = &pixels[4 * 32 * (row * width + col)];size_t dest_row_size = width * 4;size_t src_row_size = 32 * 4;if (blend){for (unsigned int r = 0; r < 32; r++){for (unsigned int c = 0; c < 32; c++){unsigned char a = src[3];unsigned char inv_a = 255 - src[3];dest[0] = (src[0] * a + dest[0] * inv_a) / 255;dest[1] = (src[1] * a + dest[1] * inv_a) / 255;dest[2] = (src[2] * a + dest[2] * inv_a) / 255;dest[3] = (src[3] * a + dest[3] * inv_a) / 255;dest += 4;src += 4;}dest += dest_row_size - src_row_size;}}else{for (unsigned int r = 0; r < 32; r++){memcpy(dest, src, src_row_size);dest += dest_row_size;src += src_row_size;}}}// Copy a 32x32 image at index idx from pixels into dest.static void _copy_into(unsigned char *dest, unsigned char *pixels,unsigned int width,unsigned int height, int idx){const unsigned int tile_size = 32;const unsigned int tiles_per_row = width / tile_size;unsigned int row = idx / tiles_per_row;unsigned int col = idx % tiles_per_row;unsigned char *src = &pixels[4 * 32 * (row * width + col)];size_t src_row_size = width * 4;size_t dest_row_size = 32 * 4;for (unsigned int r = 0; r < 32; r++){memcpy(dest, src, dest_row_size);dest += dest_row_size;src += src_row_size;}}// Stores "over" on top of "under" in the location of "over".static void _copy_under(unsigned char *pixels, unsigned int width,unsigned int height, int idx_under, int idx_over){size_t image_size = 32 * 32 * 4;// Make a copy of the original images on the stack.unsigned char *under = new unsigned char[image_size];_copy_into(under, pixels, width, height, idx_under);unsigned char *over = new unsigned char[image_size];_copy_into(over, pixels, width, height, idx_over);// Replace the over image with the under image_copy_onto(pixels, width, height, under, idx_over, false);// Blend the over image over top._copy_onto(pixels, width, height, over, idx_over, true);delete[] under;delete[] over;}static bool _process_item_image(unsigned char *pixels,unsigned int width, unsigned int height){for (int i = 0; i < NUM_POTIONS; i++){int special = you.item_description[IDESC_POTIONS][i];int tile0 = TILE_POTION_OFFSET + special % 14;int tile1 = TILE_POT_HEALING + i;_copy_under(pixels, width, height, tile0, tile1);}for (int i = 0; i < NUM_WANDS; i++){int special = you.item_description[IDESC_WANDS][i];int tile0 = TILE_WAND_OFFSET + special % 12;int tile1 = TILE_WAND_FLAME + i;_copy_under(pixels, width, height, tile0, tile1);}for (int i = 0; i < STAFF_SMITING; i++){int special = you.item_description[IDESC_STAVES][i];int tile0 = TILE_STAFF_OFFSET + (special / 4) % 10;int tile1 = TILE_STAFF_WIZARDRY + i;_copy_under(pixels, width, height, tile0, tile1);}for (int i = STAFF_SMITING; i < NUM_STAVES; i++){int special = you.item_description[IDESC_STAVES][i];int tile0 = TILE_ROD_OFFSET + (special / 4) % 10;int tile1 = TILE_ROD_SMITING + i - STAFF_SMITING;_copy_under(pixels, width, height, tile0, tile1);}return true;}bool ImageManager::load_item_texture(){// We need to load images in two passes: one for the title and one// for the items. To handle identifiable items, the texture itself// is modified. So, it cannot be loaded until after the item// description table has been initialised.GenericTexture::MipMapOptions mip = GenericTexture::MIPMAP_CREATE;return m_textures[TEX_DEFAULT].load_texture("tile.png", mip,&_process_item_image);}void ImageManager::unload_textures(){for (unsigned int i = 0; i < TEX_MAX; i++){m_textures[i].unload_texture();}}
struct mcache_entry{int mon_tile;int equ_tile;int draco;};std::vector<mcache_entry> mcache;int get_base_idx_from_mcache(int tile_idx){int mcache_idx = tile_idx - TILE_MCACHE_START;if (mcache_idx >= 0 && mcache_idx < (int)mcache.size()){return mcache[mcache_idx].mon_tile;}return tile_idx;}bool get_mcache_entry(int tile_idx, int &mon_idx, int &equ_tile, int &draco){int mcache_idx = tile_idx - TILE_MCACHE_START;if (mcache_idx >= 0 && (unsigned int)mcache_idx < mcache.size()){mon_idx = mcache[mcache_idx].mon_tile;equ_tile = mcache[mcache_idx].equ_tile;draco = mcache[mcache_idx].draco;return true;}return false;}static int _mcache_register(int mon_tile, int equ_tile, int draco = 0){mcache_entry entry;entry.mon_tile = mon_tile;entry.equ_tile = equ_tile;entry.draco = draco;
env.tile_flavor[x][y].floor = floor_flavor;env.tile_flavor[x][y].wall = wall_flavor;
env.tile_flv[x][y].floor = get_floor_tile_idx() + floor_flavor;env.tile_flv[x][y].wall = get_wall_tile_idx() + wall_flavor;
if (env.tile_flavor[x][y].special != SPECIAL_N&& env.tile_flavor[x][y].special != SPECIAL_S&& env.tile_flavor[x][y].special != SPECIAL_E&& env.tile_flavor[x][y].special != SPECIAL_W)
if (env.tile_flv[x][y].special != SPECIAL_N&& env.tile_flv[x][y].special != SPECIAL_S&& env.tile_flv[x][y].special != SPECIAL_E&& env.tile_flv[x][y].special != SPECIAL_W)
wall_flv = env.tile_flavor[gx][gy].wall;floor_flv = env.tile_flavor[gx][gy].floor;special_flv = env.tile_flavor[gx][gy].special;
wall_flv = env.tile_flv[gx][gy].wall;floor_flv = env.tile_flv[gx][gy].floor;special_flv = env.tile_flv[gx][gy].special;
void tile_draw_dungeon(unsigned int *tileb){tile_finish_dngn(tileb, you.x_pos, you.y_pos);TileDrawDungeon(tileb);}#define swapint(a, b) {int tmp = a; a = b; b = tmp;}// Item is unided(1) or tried(2) or id'ed (0)static int _item_unid_type(const item_def &item){if ((item.flags & ISFLAG_KNOW_TYPE) != 0)return 0;const int s = item.sub_type;const id_arr& id = get_typeid_array();int id0 = 0;
switch (item.base_type){case OBJ_STAVES:id0 = id[ IDTYPE_STAVES ][s];if (id0 != ID_KNOWN_TYPE)return 1;elsereturn 0;case OBJ_SCROLLS:id0 = id[ IDTYPE_SCROLLS ][s];break;case OBJ_WANDS:id0 = id[ IDTYPE_WANDS ][s];break;case OBJ_POTIONS:id0 = id[ IDTYPE_POTIONS ][s];break;case OBJ_JEWELLERY:if (is_artefact(item)){if (item.props.exists("jewellery_tried")&& item.props["jewellery_tried"].get_bool()){return 2;}return 1;}id0 = id[ IDTYPE_JEWELLERY ][s];break;default:return 0;}if (id0 == ID_TRIED_TYPE)return 2;else if (id0 != ID_KNOWN_TYPE)return 1;return 0;}// Helper routine: sort floor item index and pack into idx.static int _pack_floor_item(int *idx, int *flag, int *isort, int max){int n = 0;static int isort_weapon2[NUM_WEAPONS];static int isort_armour2[NUM_ARMOURS];static const int isort_weapon[NUM_WEAPONS] ={WPN_WHIP, WPN_CLUB, WPN_HAMMER, WPN_MACE,WPN_FLAIL, WPN_DEMON_WHIP,WPN_ANKUS, WPN_MORNINGSTAR, WPN_EVENINGSTAR,WPN_SPIKED_FLAIL, WPN_GREAT_MACE, WPN_DIRE_FLAIL,WPN_GIANT_CLUB, WPN_GIANT_SPIKED_CLUB,WPN_KNIFE, WPN_DAGGER, WPN_SHORT_SWORD, WPN_SABRE, WPN_QUICK_BLADE,WPN_FALCHION, WPN_LONG_SWORD, WPN_SCIMITAR, WPN_KATANA,WPN_DEMON_BLADE, WPN_DOUBLE_SWORD, WPN_GREAT_SWORD, WPN_TRIPLE_SWORD,WPN_HAND_AXE, WPN_WAR_AXE, WPN_BROAD_AXE,WPN_BATTLEAXE, WPN_EXECUTIONERS_AXE,WPN_SPEAR, WPN_TRIDENT, WPN_HALBERD, WPN_SCYTHE,WPN_GLAIVE, WPN_DEMON_TRIDENT,WPN_QUARTERSTAFF,WPN_SLING, WPN_BOW, WPN_CROSSBOW, WPN_HAND_CROSSBOW};static const int isort_armour[NUM_ARMOURS] ={ARM_ROBE,ARM_ANIMAL_SKIN,ARM_LEATHER_ARMOUR,ARM_TROLL_LEATHER_ARMOUR,ARM_RING_MAIL, ARM_SCALE_MAIL, ARM_CHAIN_MAIL,ARM_SPLINT_MAIL, ARM_BANDED_MAIL, ARM_PLATE_MAIL,ARM_CRYSTAL_PLATE_MAIL,ARM_SWAMP_DRAGON_ARMOUR,ARM_MOTTLED_DRAGON_ARMOUR,ARM_STEAM_DRAGON_ARMOUR,ARM_DRAGON_ARMOUR,ARM_ICE_DRAGON_ARMOUR,ARM_STORM_DRAGON_ARMOUR,ARM_GOLD_DRAGON_ARMOUR,ARM_TROLL_HIDE,ARM_SWAMP_DRAGON_HIDE,ARM_MOTTLED_DRAGON_HIDE,ARM_STEAM_DRAGON_HIDE,ARM_DRAGON_HIDE,ARM_ICE_DRAGON_HIDE,ARM_STORM_DRAGON_HIDE,ARM_GOLD_DRAGON_HIDE,ARM_CLOAK,ARM_BUCKLER, ARM_SHIELD, ARM_LARGE_SHIELD,ARM_HELMET, ARM_GLOVES, ARM_BOOTS};for (int i = 0; i < NUM_WEAPONS; i++)isort_weapon2[isort_weapon[i]] = i;for (int i = 0; i < NUM_ARMOURS; i++)isort_armour2[isort_armour[i]] = i;int o = igrd[you.x_pos][you.y_pos];if (o == NON_ITEM) return 0;while (o != NON_ITEM){int id0 = _item_unid_type(mitm[o]);int next = mitm[o].link;int typ = mitm[o].base_type;if (n >= max) break;idx[n] = o;isort[n] = typ * 256 * 3;if (typ == OBJ_WEAPONS){isort[n] += 3 * isort_weapon2[ mitm[o].sub_type];}if (typ == OBJ_ARMOUR){isort[n] += 3 * isort_armour2[ mitm[o].sub_type ];}flag[n] = 0;if (item_ident( mitm[o], ISFLAG_KNOW_CURSE ) &&item_cursed(mitm[o])){flag[n] |= TILEI_FLAG_CURSE;}if (id0 != 0){isort[n] += id0;if (id0 == 2)flag[n] = TILEI_FLAG_TRIED;}flag[n] |= TILEI_FLAG_FLOOR;// Simple Bubble sortint k = n;while (k > 0 && isort[k-1] > isort[k]){swapint(idx[k-1], idx[k]);swapint(isort[k-1], isort[k]);swapint(flag[k-1], flag[k]);k--;}n++;o = next;}return n;}// Helper routine: Calculate tile index and quantity data to be displayedstatic void _finish_inven_data(int n, int *tiles, int *num, int *idx,int *iflag){int i;for (i = 0; i < n; i++){int q = -1;int j = idx[i];item_def *itm;if (j == -1){num[i] = -1;tiles[i] = 0;continue;}if (iflag[i] & TILEI_FLAG_FLOOR)itm = &mitm[j];elseitm = &you.inv[j];int type = itm->base_type;if (type == OBJ_FOOD || type == OBJ_SCROLLS|| type == OBJ_POTIONS || type == OBJ_MISSILES){q = itm->quantity;}if (q == 1)q = -1;if (type == OBJ_WANDS&& ((itm->flags & ISFLAG_KNOW_PLUSES)|| itm->plus2 == ZAPCOUNT_EMPTY)){q = itm->plus;}tiles[i] = tileidx_item(*itm);num[i] = q;}}// Display Inventory/floor items#include "guic.h"extern TileRegionClass *region_item;extern TileRegionClass *region_item2;extern WinClass *win_main;void tile_draw_inv(int flag){// "inventory" including items on floor#define MAXINV 200int tiles[MAXINV];int num[MAXINV];int idx[MAXINV];int iflag[MAXINV];int isort[MAXINV];if (flag == -1){flag = (win_main->active_layer == 0) ? REGION_INV1: REGION_INV2;}TileRegionClass *r = (flag == REGION_INV1) ? region_item: region_item2;int numInvTiles = r->mx * r->my;if (numInvTiles > MAXINV)numInvTiles = MAXINV;// Show one row of ground tiles, no matter what. This may cause some// items not to show up, but theoretically you've ordered tile_show_items// to prioritize the important stuff.int max_inventory_items = std::min(numInvTiles - r->mx, ENDOFPACK);// which items to show in inventoryconst char *item_chars = Options.tile_show_items;// show no items, pleaseif (item_chars[0] == 0)return;int eq_flag[ENDOFPACK];int empty = 0; // counts empty slots// first set eq_flag = 1 for all slots that actually hold valid items// XXX: Why? --jpegfor (int i = 0; i < max_inventory_items; i++){eq_flag[i] =(you.inv[i].quantity != 0 && is_valid_item( you.inv[i])) ? 1 : 0;if (!eq_flag[i])empty++;}// next, increase eq_flag to 2 if it's actually equipped// FIX ME: Doesn't check for sensible equipment, i.e.// wielded armour counts, toofor (int eq = 0; eq < NUM_EQUIP; eq++){int slot = you.equip[eq];if (slot >= 0 && slot < ENDOFPACK)eq_flag[slot] = 2;}int n = 0;// item.base_type <-> char conversion tableconst static char *obj_syms = ")([/%#?=!#+\\0}x";for (int i = 0; i < (int)strlen(item_chars); i++){int top = n;char ic = item_chars[i];if (n >= numInvTiles)break;// Items on the floorif (ic == '.'){n += _pack_floor_item(&idx[n], &iflag[n], &isort[n],numInvTiles - n);continue;}// empty slotsif (ic == '_'){for (int j = 0; j < empty && n < numInvTiles; j++){idx[n] = -1;iflag[n] = 0;n++;}continue;}// convert item char to item typeint type = -1;for (int j = 0; j < (int)strlen(obj_syms); j++){if (obj_syms[j] == ic){type = j;break;}}if (type == -1)continue;for (int j = 0; j < max_inventory_items && n < numInvTiles; j++){if (you.inv[j].base_type == type && eq_flag[j] != 0){int sval = NUM_EQUIP + you.inv[j].sub_type;int base = 0;int id0 = _item_unid_type(you.inv[j]);idx[n] = j;iflag[n] = 0;if (type == OBJ_JEWELLERY && sval >= AMU_RAGE){base = 1000;sval = base + sval;}if (id0 == 2){iflag[n] |= TILEI_FLAG_TRIED;// To the tailsval = base + 980;}else if (id0 == 1){// To the tailsval = base + 990;}// Equipment firstif (eq_flag[j] == 2){//sval = base;iflag[n] |= TILEI_FLAG_EQUIP;}if (item_cursed(you.inv[j])&& item_ident( you.inv[j], ISFLAG_KNOW_CURSE )){iflag[n] |= TILEI_FLAG_CURSE;}if (flag == REGION_INV2)sval = j;isort[n] = sval;int k = n;while (k > top && isort[k-1] > isort[k]){swapint(idx[k-1], idx[k]);swapint(isort[k-1], isort[k]);swapint(iflag[k-1], iflag[k]);k--;}n++;} // type == base} // j} // i_finish_inven_data(n, tiles, num, idx, iflag);for (int i = n; i < numInvTiles; i++){tiles[i] = 0;num[i] = 0;idx[i] = -1;iflag[i] = 0;}TileDrawInvData(n, flag, tiles, num, idx, iflag);}
/** File: tilefont.h* Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: ennewalker $ on $Date: 2008-03-07 $*/#ifndef TILEFONT_H#define TILEFONT_H#include "AppHdr.h"#include "externs.h"#include "tiletex.h"// This class handles loading FreeType2 fonts and rendering them via OpenGL.// TODO enne - Fonts could be made better by://// * handling kerning//// * the possibility of streaming this class in and out so that Crawl doesn't// have to link against FreeType2 or be forced do as much processing at// load time.class FTFont{public:FTFont();virtual ~FTFont();bool load_font(const char *font_name, unsigned int font_size);// render just textvoid render_textblock(unsigned int x, unsigned int y,unsigned char *chars, unsigned char *colours,unsigned int width, unsigned int height,bool drop_shadow = false);// render text + background boxvoid render_string(unsigned int x, unsigned int y, const char *text,const coord_def &min_pos, const coord_def &max_pos,unsigned char font_colour, bool drop_shadow = false,unsigned char box_alpha = 0,unsigned char box_colour = 0, unsigned int outline = 0);unsigned int char_width() const { return m_max_advance.x; }unsigned int char_height() const { return m_max_advance.y; }protected:struct GlyphInfo{// offset before drawing glyph; can be negativeint offset;// per-glyph horizontal advanceint advance;bool renderable;};GlyphInfo *m_glyphs;// cached value of the maximum advance from m_advancecoord_def m_max_advance;// minimum offset (likely negative)int m_min_offset;GenericTexture m_tex;};#endif
/** File: tilefont.cc* Created by: ennewalker on Sat Apr 26 01:33:53 2008 UTC** Modified for Crawl Reference by $Author: ennewalker $ on $Date: 2008-03-07 $*/#include "tilefont.h"#include "defines.h"#include <SDL.h>#include <SDL_opengl.h>#include <ft2build.h>#include FT_FREETYPE_Hconst unsigned char term_colours[MAX_TERM_COLOUR][3] ={{ 0, 0, 0}, // BLACK{ 0, 82, 255}, // BLUE{100, 185, 70}, // GREEN{ 0, 180, 180}, // CYAN{255, 48, 0}, // RED{238, 92, 238}, // MAGENTA{165, 91, 0}, // BROWN{162, 162, 162}, // LIGHTGREY{ 82, 82, 82}, // DARKGREY{ 82, 102, 255}, // LIGHTBLUE{ 82, 255, 82}, // LIGHTGREEN{ 82, 255, 255}, // LIGHTCYAN{255, 82, 82}, // LIGHTRED{255, 82, 255}, // LIGHTMAGENTA{255, 255, 82}, // YELLOW{255, 255, 255} // WHITE};FTFont::FTFont() :m_glyphs(NULL),m_max_advance(0, 0),m_min_offset(0){}FTFont::~FTFont(){delete[] m_glyphs;}bool FTFont::load_font(const char *font_name, unsigned int font_size){FT_Library library;FT_Face face;FT_Error error;error = FT_Init_FreeType(&library);if (error){fprintf(stderr, "Failed to initialize freetype library.\n");return false;}error = FT_New_Face(library, font_name, 0, &face);if (error == FT_Err_Unknown_File_Format){fprintf(stderr, "Unknown font format for file '%s'\n", font_name);return false;}else if (error){fprintf(stderr, "Invalid font from file '%s'\n", font_name);}error = FT_Set_Pixel_Sizes(face, font_size, font_size);ASSERT(!error);// Get maximum advancem_max_advance = coord_def(0,0);int ascender = face->ascender >> 6;int min_y = 100000; // TODO enne - fix meint max_y = 0;m_min_offset = 0;m_glyphs = new GlyphInfo[256];for (unsigned int c = 0; c < 256; c++){m_glyphs[c].offset = 0;m_glyphs[c].advance = 0;m_glyphs[c].renderable = false;FT_Int glyph_index = FT_Get_Char_Index(face, c);if (!glyph_index){continue;}error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);ASSERT(!error);FT_Bitmap *bmp = &face->glyph->bitmap;int advance = face->glyph->advance.x >> 6;m_max_advance.x = std::max(m_max_advance.x, advance);min_y = std::min(min_y, ascender - face->glyph->bitmap_top);max_y = std::max(max_y, ascender + bmp->rows - face->glyph->bitmap_top);m_glyphs[c].offset = face->glyph->bitmap_left;m_glyphs[c].advance = advance;m_min_offset = std::min(m_min_offset, m_glyphs[c].offset);}// TEMP enne - this seems to be broken on OSX - it returns 8, when it should be 2?m_max_advance.x = 10;// The ascender and text height given by FreeType2 is ridiculously large// (e.g. 37 pixels high for 14 pixel font). Use min and max bounding// heights on the characters we care about to get better values for the// text height and the ascender.m_max_advance.y = max_y - min_y;ascender -= min_y;// Grow character size to power of 2coord_def charsz(1,1);while (charsz.x < m_max_advance.x)charsz.x *= 2;while (charsz.y < m_max_advance.y)charsz.y *= 2;// Fill out texture to be (16*charsz.x) X (16*charsz.y) X (32-bit)// Having to blow out 8-bit alpha values into full 32-bit textures is// kind of frustrating, but not all OpenGL implementations support the// "esoteric" ALPHA8 format and it's not like this texture is very large.unsigned int width = 16 * charsz.x;unsigned int height = 16 * charsz.y;unsigned char *pixels = new unsigned char[4 * width * height];memset(pixels, 0, sizeof(unsigned char) * 4 * width * height);for (unsigned int c = 0; c < 256; c++){FT_Int glyph_index = FT_Get_Char_Index(face, c);if (!glyph_index){// If no mapping for this character, leave blank.continue;}error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);ASSERT(!error);FT_Bitmap *bmp = &face->glyph->bitmap;ASSERT(bmp);// Some glyphs (e.g. " ") don't get a buffer.if (!bmp->buffer)continue;m_glyphs[c].renderable = true;int vert_offset = ascender - face->glyph->bitmap_top;ASSERT(bmp->pixel_mode == FT_PIXEL_MODE_GRAY);ASSERT(bmp->num_grays == 256);ASSERT(bmp->width + face->glyph->bitmap_left <= m_max_advance.x);ASSERT(bmp->rows <= m_max_advance.y);ASSERT(vert_offset >= 0);ASSERT(vert_offset + bmp->rows <= m_max_advance.y);// Horizontal offset stored in m_glyphs and handled when drawingunsigned int offset_x = (c % 16) * charsz.x;unsigned int offset_y = (c / 16) * charsz.y + vert_offset;for (int x = 0; x < bmp->width; x++)for (int y = 0; y < bmp->rows; y++){unsigned int idx = offset_x + x + (offset_y + y) * width;idx *= 4;unsigned char alpha = bmp->buffer[x + bmp->width * y];pixels[idx] = 255;pixels[idx + 1] = 255;pixels[idx + 2] = 255;pixels[idx + 3] = alpha;}}bool success = m_tex.load_texture(pixels, width, height,GenericTexture::MIPMAP_NONE);delete[] pixels;return success;}struct FontVertLayout{float pos_x;float pos_y;float tex_x;float tex_y;unsigned char r;unsigned char g;unsigned char b;unsigned char a;};void FTFont::render_textblock(unsigned int x_pos, unsigned int y_pos,unsigned char *chars, unsigned char *colours,unsigned int width, unsigned int height,bool drop_shadow){if (!chars || !colours || !width || !height || !m_glyphs)return;coord_def adv(std::max(-m_min_offset, 0), 0);unsigned int i = 0;std::vector<FontVertLayout> verts;// TODO enne - make this better// This is bad for the CRT. Maybe we should just reserve some fixed limit?// Maybe we should just cache this in FTFont?verts.reserve(4 * width * height);float texcoord_dy = (float)m_max_advance.y / (float)m_tex.height();for (unsigned int y = 0; y < height; y++){for (unsigned int x = 0; x < width; x++){unsigned char c = chars[i];unsigned int this_adv = m_glyphs[c].advance + 1;adv.x += m_glyphs[c].offset;if (m_glyphs[c].renderable){unsigned char col = colours[i];float tex_x = (float)(c % 16) / 16.0f;float tex_y = (float)(c / 16) / 16.0f;float tex_x2 = tex_x + (float)this_adv / (float)m_tex.width();float tex_y2 = tex_y + texcoord_dy;FontVertLayout v;v.pos_x = adv.x;v.pos_y = adv.y;v.tex_x = tex_x;v.tex_y = tex_y;v.r = term_colours[col][0];v.g = term_colours[col][1];v.b = term_colours[col][2];v.a = 255;verts.push_back(v);v.pos_x = adv.x;v.pos_y = adv.y + m_max_advance.y;v.tex_x = tex_x;v.tex_y = tex_y2;v.r = term_colours[col][0];v.g = term_colours[col][1];v.b = term_colours[col][2];v.a = 255;verts.push_back(v);v.pos_x = adv.x + this_adv;v.pos_y = adv.y + m_max_advance.y;v.tex_x = tex_x2;v.tex_y = tex_y2;v.r = term_colours[col][0];v.g = term_colours[col][1];v.b = term_colours[col][2];v.a = 255;verts.push_back(v);v.pos_x = adv.x + this_adv;v.pos_y = adv.y;v.tex_x = tex_x2;v.tex_y = tex_y;v.r = term_colours[col][0];v.g = term_colours[col][1];v.b = term_colours[col][2];v.a = 255;verts.push_back(v);}i++;adv.x += this_adv - m_glyphs[c].offset - 1;}adv.x = 0;adv.y += m_max_advance.y;}if (!verts.size())return;GLState state;state.array_vertex = true;state.array_texcoord = true;state.blend = true;state.texture = true;GLStateManager::set(state);m_tex.bind();glVertexPointer(2, GL_FLOAT, sizeof(FontVertLayout), &verts[0].pos_x);glTexCoordPointer(2, GL_FLOAT, sizeof(FontVertLayout), &verts[0].tex_x);if (drop_shadow){glColor3f(0.0f, 0.0f, 0.0f);glLoadIdentity();glTranslatef(x_pos + 1, y_pos + 1, 0.0f);glDrawArrays(GL_QUADS, 0, verts.size());glColor3f(1.0f, 1.0f, 1.0f);}glLoadIdentity();glTranslatef(x_pos, y_pos, 0.0f);glEnableClientState(GL_COLOR_ARRAY);glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(FontVertLayout), &verts[0].r);glDrawArrays(GL_QUADS, 0, verts.size());glDisableClientState(GL_COLOR_ARRAY);}struct box_vert{float x;float y;unsigned char r;unsigned char g;unsigned char b;unsigned char a;};static void _draw_box(int x_pos, int y_pos, float width, float height,float box_width, unsigned char box_colour,unsigned char box_alpha){box_vert verts[4];for (unsigned int i = 0; i < 4; i++){verts[i].r = term_colours[box_colour][0];verts[i].g = term_colours[box_colour][1];verts[i].b = term_colours[box_colour][2];verts[i].a = box_alpha;}verts[0].x = x_pos - box_width;verts[0].y = y_pos - box_width;verts[1].x = verts[0].x;verts[1].y = y_pos + height + box_width;verts[2].x = x_pos + width + box_width;verts[2].y = verts[1].y;verts[3].x = verts[2].x;verts[3].y = verts[0].y;glLoadIdentity();GLState state;state.array_vertex = true;state.array_colour = true;state.blend = true;GLStateManager::set(state);glVertexPointer(2, GL_FLOAT, sizeof(box_vert), &verts[0].x);glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(box_vert), &verts[0].r);glDrawArrays(GL_QUADS, 0, sizeof(verts) / sizeof(box_vert));}void FTFont::render_string(unsigned int px, unsigned int py,const char *text,const coord_def &min_pos, const coord_def &max_pos,unsigned char font_colour, bool drop_shadow,unsigned char box_alpha,unsigned char box_colour,unsigned int outline){ASSERT(text);// Determine extent of this textunsigned int max_rows = 1;unsigned int cols = 0;unsigned int max_cols = 0;for (const char *itr = text; *itr; itr++){cols++;max_cols = std::max(cols, max_cols);// NOTE: only newlines should be used for tool tips. Don't use EOL.ASSERT(*itr != '\r');if (*itr == '\n'){cols = 0;max_rows++;}}// Create the text blockunsigned char *chars = (unsigned char *)alloca(max_rows * max_cols);unsigned char *colours = (unsigned char *)alloca(max_rows * max_cols);memset(chars, ' ', max_rows * max_cols);memset(colours, font_colour, max_rows * max_cols);// Fill the text blockcols = 0;unsigned int rows = 0;for (const char *itr = text; *itr; itr++){chars[cols + rows * max_cols] = *itr;cols++;if (*itr == '\n'){cols = 0;rows++;}}// Find a suitable location on screenconst int buffer = 5; // additional buffer size from edgesint wx = max_cols * char_width();int wy = max_rows * char_height();// text starting locationint tx = px - wx / 2;int ty = py - wy - outline;// box with extra buffer to test against min_pos/max_pos window sizeint sx = tx - buffer;int sy = ty - buffer;int ex = sx + wx + buffer;int ey = sy + wy + buffer;if (ex > max_pos.x)tx += max_pos.x - ex;else if (sx < min_pos.x)tx -= sx;if (ey > max_pos.y)ty += max_pos.y - ey;else if (sy < min_pos.y)ty -= sy;if (box_alpha != 0)_draw_box(tx, ty, wx, wy, outline, box_colour, box_alpha);render_textblock(tx, ty, chars, colours, max_cols, max_rows, drop_shadow);}
// normal tile count + iso tile count#define TILE_TOTAL2 (TILE_TOTAL)// normal tile count#define TILE_NORMAL TILE_TOTALextern void TileDrawDungeonAux();// Raw tile imagesextern img_type TileImg;extern img_type PlayerImg;extern img_type WallImg;extern img_type ScrBufImg;extern WinClass *win_main;// Regionsextern TileRegionClass *region_tile;extern TextRegionClass *region_crt;extern TextRegionClass *region_stat;extern TextRegionClass *region_tip;extern TextRegionClass *region_msg;extern TileRegionClass *region_item;extern TileRegionClass *region_item2;#define ScrBufImg (region_tile->backbuf)//Internalstatic img_type DollCacheImg;static void _tile_draw_grid(int xx, int yy);static void _clear_tcache();static void _init_tcache();static void _register_tile_mask(int tile, int *cp,char *ms, bool smalltile = false);static void _tcache_compose_normal(int ix, int *fg, int *bg);static void _mcache_init();//Internal variablesstatic bool force_redraw_tile = false;static bool force_redraw_inv = false;void tile_set_force_redraw_tiles(bool redraw){force_redraw_tile = redraw;}void tile_set_force_redraw_inv(bool redraw){force_redraw_inv = redraw;}static unsigned int t1buf[TILE_DAT_XMAX+2][TILE_DAT_YMAX+2],t2buf[TILE_DAT_XMAX+2][TILE_DAT_YMAX+2];static unsigned int tb_bk[TILE_DAT_YMAX*TILE_DAT_XMAX*2];#define MAX_ITEMLIST 200int itemlist[MAX_ITEMLIST];int itemlist_num[MAX_ITEMLIST];int itemlist_idx[MAX_ITEMLIST];char itemlist_key[MAX_ITEMLIST];int itemlist_iflag[MAX_ITEMLIST];int itemlist_flag = -1;int itemlist_n = 0;
/******** Cache buffer for transparency operation *****/static int last_cursor = -1;//Internal cache Image bufferstatic img_type tcache_image = 0;//Start of a pointer stringstatic int tcache_head;typedef struct tile_cache{unsigned int id[2];int idx;tile_cache *next;tile_cache *prev;} tile_cache;// number of tile gridsstatic int tile_xmax;static int tile_ymax;static int max_tcache;// [max_tcache]static tile_cache *tcache;// [x*y]static int *screen_tcache_idx;const int tcache_wx_normal = TILE_X;const int tcache_wy_normal = TILE_Y;const int tcache_ox_normal = 0;const int tcache_oy_normal = 0;const int tcache_nlayer_normal = 1;const int region_sx_normal = 0;const int region_sy_normal = 0;const int region_wx_normal = TILE_X;const int region_wy_normal = TILE_Y;
// ISO mode sink maskstatic char *sink_mask;/********* Image manipulation subroutines ****************/img_type ImgLoadFileSimple(const char *name){char fname[512];#ifdef USE_X11sprintf(fname,"tiles/%s.png", name);std::string path = datafile_path(fname, true, true);return ImgLoadFile(path.c_str());#endif#ifdef WIN32TILESsprintf(fname,"tiles/%s.bmp", name);std::string path = datafile_path(fname, true, true);return ImgLoadFile(path.c_str());#endif}// TileImg macrovoid _ImgCopyFromTileImg(int idx, img_type dest, int dx, int dy, int copy,char *mask = NULL, bool hilite = false){int sx = (idx % TILE_PER_ROW)*TILE_X;int sy = (idx / TILE_PER_ROW)*TILE_Y;if (hilite){if (mask != NULL)ImgCopyMaskedH(TileImg, sx, sy, TILE_X, TILE_Y,dest, dx, dy, mask);elseImgCopyH(TileImg, sx, sy, TILE_X, TILE_Y, dest, dx, dy, copy);}else{if (mask != NULL)ImgCopyMasked(TileImg, sx, sy, TILE_X, TILE_Y,dest, dx, dy, mask);elseImgCopy(TileImg, sx, sy, TILE_X, TILE_Y, dest, dx, dy, copy);}}static void _ImgCopyToTileImg(int idx, img_type src, int sx, int sy, int copy,char *mask = NULL, bool hilite = false){int dx = (idx % TILE_PER_ROW)*TILE_X;int dy = (idx / TILE_PER_ROW)*TILE_Y;if (hilite){if (mask != NULL)ImgCopyMaskedH(src, sx, sy, TILE_X, TILE_Y,TileImg, dx, dy, mask);elseImgCopyH(src, sx, sy, TILE_X, TILE_Y, TileImg, dx, dy, copy);}else{if (mask != NULL)ImgCopyMasked(src, sx, sy, TILE_X, TILE_Y,TileImg, dx, dy, mask);elseImgCopy(src, sx, sy, TILE_X, TILE_Y, TileImg, dx, dy, copy);}}void TileInit(){textcolor(WHITE);TileImg = ImgLoadFileSimple("tile");PlayerImg = ImgLoadFileSimple("player");WallImg = ImgLoadFileSimple("wall2d");if (!TileImg){cprintf("Main tile not initialized\n");getch();end(-1);}ImgSetTransparentPix(TileImg);if (ImgWidth(TileImg)!= TILE_X * TILE_PER_ROW|| ImgHeight(TileImg) <TILE_Y * ((TILE_TOTAL + TILE_PER_ROW -1)/TILE_PER_ROW) ){cprintf("Main tile size invalid\n");getch();end(-1);}if (!PlayerImg){cprintf("Player tile not initialized\n");getch();end(-1);}if (ImgWidth(PlayerImg)!= TILE_X * TILEP_PER_ROW){cprintf("Player tile size invalid\n");getch();end(-1);}if (!WallImg){cprintf("wall2d tile not initialized\n");getch();end(-1);}tile_xmax = tile_dngn_x;tile_ymax = tile_dngn_y;max_tcache = 4*tile_xmax*tile_ymax;screen_tcache_idx = (int *)malloc(sizeof(int)* tile_xmax * tile_ymax);tcache = (tile_cache *)malloc(sizeof(tile_cache)*max_tcache);for (int x = 0; x < tile_xmax * tile_ymax; x++)screen_tcache_idx[x] = -1;sink_mask = (char *)malloc(TILE_X*TILE_Y);_init_tcache();DollCacheImg = ImgCreateSimple(TILE_X, TILE_Y);for (int x = 0; x < TILE_DAT_XMAX + 2; x++){for (int y = 0; y < TILE_DAT_YMAX + 2; y++){t1buf[x][y] = 0;t2buf[x][y] = TILE_DNGN_UNSEEN|TILE_FLAG_UNSEEN;}}force_redraw_tile = false;_mcache_init();for (int x = 0; x < MAX_ITEMLIST; x++)itemlist[x] = itemlist_num[x] = itemlist_key[x] = itemlist_idx[x] = 0;}void TileResizeScreen(int x0, int y0){tile_xmax = x0;tile_ymax = y0;max_tcache = 4*tile_xmax*tile_ymax;free(screen_tcache_idx);screen_tcache_idx = (int *)malloc(sizeof(int)* tile_xmax * tile_ymax);free(tcache);tcache = (tile_cache *)malloc(sizeof(tile_cache)*max_tcache);for (int x = 0; x < tile_xmax * tile_ymax; x++)screen_tcache_idx[x] = -1;_init_tcache();crawl_view.viewsz.x = tile_xmax;crawl_view.viewsz.y = tile_ymax;crawl_view.vbuf.size(crawl_view.viewsz);}void _clear_tcache(){tcache_head = 0;for (int i = 0; i < max_tcache; i++){tcache[i].id[1] = tcache[i].id[0] = 0;tcache[i].idx = i;if (i == 0)tcache[i].prev = NULL;elsetcache[i].prev = &tcache[i-1];if (i == max_tcache - 1)tcache[i].next = NULL;elsetcache[i].next = &tcache[i+1];}}void _init_tcache(){_clear_tcache();ImgDestroy(tcache_image);tcache_image = ImgCreateSimple(tcache_wx_normal,max_tcache*tcache_wy_normal);}// Move a cache to the top of pointer string// to shorten the search timestatic void _lift_tcache(int ix){int head_old = tcache_head;tile_cache *p = tcache[ix].prev;tile_cache *n = tcache[ix].next;ASSERT(ix < max_tcache);ASSERT(head_old < max_tcache);if (ix == head_old)return;if (p!=NULL)p->next = n;if (n!=NULL)n->prev = p;tcache_head = ix;tcache[head_old].prev = &tcache[ix];tcache[ix].next = &tcache[head_old];}// Find cached image of fg+bg// If not found, compose and cache itstatic int _tcache_find_id_normal(int *fg, int *bg, int *is_new){tile_cache *tc0 = &tcache[tcache_head];*is_new = 0;while (true){tile_cache *next = tc0->next;if ((int)tc0->id[0] == fg[0] && (int)tc0->id[1] == bg[0])break;if (next == NULL){//end of used cache*is_new = 1;_tcache_compose_normal(tc0->idx, fg, bg);tc0->id[0] = fg[0];tc0->id[1] = bg[0];break;}tc0 = next;}_lift_tcache(tc0->idx);return (tc0->idx);}// Overlay a tile onto an existing image with transparency operation.static void _tcache_overlay(img_type img, int idx, int tile,int *copy, char *mask, unsigned int shift_left = 0){int x0, y0;int sx = region_sx_normal + shift_left;int sy = region_sy_normal;int wx = region_wx_normal - shift_left;int wy = region_wy_normal;int ox = 0;int oy = 0;img_type src = TileImg;int uy = wy;tile &= TILE_FLAG_MASK;x0 = (tile % TILE_PER_ROW) * TILE_X;y0 = (tile / TILE_PER_ROW) * TILE_Y;if (mask != NULL){if (*copy == 2){ImgCopyMaskedH(src, x0 + sx, y0 + sy, wx, wy,img, ox, oy + idx*uy, mask);}else{ImgCopyMasked(src, x0 + sx, y0 + sy, wx, wy,img, ox, oy + idx*uy, mask);}}// Hack: hilite rim colorelse if (*copy == 2){ImgCopyH(src, x0 + sx, y0 + sy, wx, wy,img, ox, oy + idx*uy, *copy);}else{ImgCopy(src, x0 + sx, y0 + sy, wx, wy,img, ox, oy + idx*uy, *copy);}*copy = 0;}void _tcache_overlay_player(img_type img, int dx, int dy, int part, int idx,int ymax, int *copy){int xs, ys;int tidx = tilep_parts_start[part];int nx = tilep_parts_nx[part];int ny = tilep_parts_ny[part];int ox = tilep_parts_ox[part];int oy = tilep_parts_oy[part];int wx = TILE_X/nx;int wy = TILE_Y/ny;if (!idx)return;idx--;tidx += idx/(nx*ny);if (oy+wy > ymax)wy -= oy + wy - ymax;if (wy <= 0)return;xs = (tidx % TILEP_PER_ROW)*TILE_X;ys = (tidx / TILEP_PER_ROW)*TILE_Y;xs += (idx % nx)*(TILE_X/nx);ys += ((idx/nx) % ny)*(TILE_Y/ny);ImgCopy(PlayerImg, xs, ys, wx, wy,img, dx+ox, dy+oy, *copy);*copy = 0;}/* overlay a tile onto an exsisting image with transpalency operation */void _register_tile_mask(int tile, int *copy,char *mask, bool smalltile){int x0, y0, x, y;int sx = region_sx_normal;int sy = region_sy_normal;int wx = region_wx_normal;int wy = region_wy_normal;int ox = 0;int oy = 0;int ux = wx;int uy = wy;img_type src = TileImg;tile &= TILE_FLAG_MASK;x0 = (tile % TILE_PER_ROW) * TILE_X;y0 = (tile / TILE_PER_ROW) * TILE_Y;if (*copy != 0)memset(mask, 0, ux*uy);if (*copy == 2){if (smalltile)ux = wx;for (x = 0; x < wx; x++)for (y = 0; y < wy; y++){if (!ImgIsTransparentAt(src, x0+sx+x, y0+sy+y))mask[(y+oy) * ux + (x+ox)] = 1;}}else{for (x = 0; x < wx; x += 2){for (y = 0; y < wy; y += 2){if (!ImgIsTransparentAt(src, x0+sx+x, y0+sy+y))mask[(y+oy) * ux + (x+ox)] = 1;}}}*copy = 0;}void _tile_draw_grid(int xx, int yy){int fg[4],bg[4],ix, ix_old, is_new;if (xx < 0 || yy < 0 || xx >= tile_xmax || yy>= tile_ymax)return;fg[0] = t1buf[xx+1][yy+1];bg[0] = t2buf[xx+1][yy+1];ix_old = screen_tcache_idx[xx+yy*tile_xmax];ix = _tcache_find_id_normal(fg, bg, &is_new);screen_tcache_idx[xx+yy*tile_xmax] = ix;if (is_new || ix!=ix_old || force_redraw_tile){int x_dest = tcache_ox_normal+xx* TILE_UX_NORMAL;int y_dest = tcache_oy_normal+yy* TILE_UY_NORMAL;int wx = tcache_wx_normal;int wy = tcache_wy_normal;ImgCopy(tcache_image, 0, ix*wy, wx, wy, ScrBufImg, x_dest, y_dest, 1);}}static void _update_single_grid(int x, int y){_tile_draw_grid(x, y);int sx = x*TILE_UX_NORMAL;int sy = y*TILE_UY_NORMAL;int wx = TILE_UX_NORMAL;int wy = TILE_UY_NORMAL;region_tile->redraw(sx, sy, sx+wx-1, sy+wy-1);}// Discard cache containing specific tilestatic void _redraw_spx_tcache(int tile){for (int idx = 0; idx < max_tcache; idx++){int fg = tcache[idx].id[0];int bg = tcache[idx].id[1];if ((fg & TILE_FLAG_MASK) == tile|| (bg & TILE_FLAG_MASK) == tile){_tcache_compose_normal(idx, &fg, &bg);}}}static void _get_bbg(int bg, int *new_bg, int *bbg){int bg0 = bg & TILE_FLAG_MASK;*bbg = TILE_DNGN_FLOOR;*new_bg = bg0;if (bg0 == TILE_DNGN_UNSEEN || bg0 == 0|| (bg0 >= TILE_DNGN_ROCK_WALL_OFS && bg0 < TILE_DNGN_WAX_WALL)){*bbg = 0;}else if (bg0 >= TILE_DNGN_FLOOR && bg0 <= TILE_DNGN_SHALLOW_WATER){*bbg = bg;*new_bg = 0;}}static int _sink_mask_tile(int bg, int fg){int bg0 = bg & TILE_FLAG_MASK;if (fg == 0 || (fg & TILE_FLAG_FLYING) != 0)return 0;if ( bg0 >= TILE_DNGN_LAVA &&bg0 <= TILE_DNGN_SHALLOW_WATER + 3){return TILE_SINK_MASK;}return 0;}//normalvoid _tcache_compose_normal(int ix, int *fg, int *bg){int bbg;int new_bg;int c = 1;int fg0 = fg[0];int bg0 = bg[0];int sink;_get_bbg(bg0, &new_bg, &bbg);if (bbg)_tcache_overlay(tcache_image, ix, bbg, &c, NULL);if (bg0 & TILE_FLAG_BLOOD)_tcache_overlay(tcache_image, ix, TILE_BLOOD0 + ix % 5, &c, NULL);if (new_bg)_tcache_overlay(tcache_image, ix, new_bg, &c, NULL);else if (bg0 & TILE_FLAG_HALO)_tcache_overlay(tcache_image, ix, TILE_HALO, &c, NULL);if ((bg0 & TILE_FLAG_SANCTUARY) && !(bg0 & TILE_FLAG_UNSEEN))_tcache_overlay(tcache_image, ix, TILE_SANCTUARY, &c, NULL);// Apply the travel exclusion under the foreground if the cell is// visible. It will be applied later if the cell is unseen.if ((bg0 & TILE_FLAG_TRAV_EXCL) && !(bg0 & TILE_FLAG_UNSEEN))_tcache_overlay(tcache_image, ix, TILE_TRAVEL_EXCLUSION, &c, NULL);else if ((bg0 & TILE_FLAG_EXCL_CTR) && !(bg0 & TILE_FLAG_UNSEEN))_tcache_overlay(tcache_image, ix, TILE_TRAVEL_EXCL_CENTRE, &c, NULL);if (bg0 & TILE_FLAG_RAY)_tcache_overlay(tcache_image, ix, TILE_RAY_MESH, &c, NULL);if (fg0){sink = _sink_mask_tile(bg0, fg0);if (sink){int flag = 2;_register_tile_mask(sink, &flag, sink_mask);_tcache_overlay(tcache_image, ix, fg0, &c, sink_mask);}else_tcache_overlay(tcache_image, ix, fg0, &c, NULL);}if (fg0 & TILE_FLAG_NET)_tcache_overlay(tcache_image, ix, TILE_TRAP_NET, &c, NULL);if (fg0 & TILE_FLAG_S_UNDER)_tcache_overlay(tcache_image, ix, TILE_SOMETHING_UNDER, &c, NULL);// Pet markint status_shift = 0;if (fg0 & TILE_FLAG_PET){_tcache_overlay(tcache_image, ix, TILE_HEART, &c, NULL);status_shift += 10;}else if ((fg0 & TILE_FLAG_MAY_STAB) == TILE_FLAG_NEUTRAL){_tcache_overlay(tcache_image, ix, TILE_NEUTRAL, &c, NULL);status_shift += 8;}else if ((fg0 & TILE_FLAG_MAY_STAB) == TILE_FLAG_STAB){_tcache_overlay(tcache_image, ix, TILE_STAB_BRAND, &c, NULL);status_shift += 8;}else if ((fg0 & TILE_FLAG_MAY_STAB) == TILE_FLAG_MAY_STAB){_tcache_overlay(tcache_image, ix, TILE_MAY_STAB_BRAND, &c,NULL);status_shift += 5;}if (fg0 & TILE_FLAG_POISON){_tcache_overlay(tcache_image, ix, TILE_POISON, &c, NULL,status_shift);status_shift += 5;}if (fg0 & TILE_FLAG_ANIM_WEP){_tcache_overlay(tcache_image, ix, TILE_ANIMATED_WEAPON, &c, NULL);}if (bg0 & TILE_FLAG_UNSEEN){_tcache_overlay(tcache_image, ix, TILE_MESH, &c, NULL);}if (bg0 & TILE_FLAG_MM_UNSEEN){_tcache_overlay(tcache_image, ix, TILE_MAGIC_MAP_MESH, &c,NULL);}// Don't let the "new stair" icon cover up any existing icons, but// draw it otherwise.if (bg0 & TILE_FLAG_NEW_STAIR && status_shift == 0)_tcache_overlay(tcache_image, ix, TILE_NEW_STAIR, &c, NULL);if ((bg0 & TILE_FLAG_TRAV_EXCL) && (bg0 & TILE_FLAG_UNSEEN)){_tcache_overlay(tcache_image, ix, TILE_TRAVEL_EXCLUSION, &c,NULL);}else if ((bg0 & TILE_FLAG_EXCL_CTR) && (bg0 & TILE_FLAG_UNSEEN)){_tcache_overlay(tcache_image, ix, TILE_TRAVEL_EXCL_CENTRE, &c,NULL);}// Tile cursorif (bg0 & TILE_FLAG_CURSOR){int type = ((bg0 & TILE_FLAG_CURSOR) == TILE_FLAG_CURSOR1) ?TILE_CURSOR : TILE_CURSOR2;if ((bg0 & TILE_FLAG_CURSOR) == TILE_FLAG_CURSOR3)type = TILE_CURSOR3;_tcache_overlay(tcache_image, ix, type, &c, NULL);if (type != TILE_CURSOR3)c = 2;}}// Tile cursorint TileDrawCursor(int x, int y, int cflag){int oldc = t2buf[x+1][y+1] & TILE_FLAG_CURSOR;t2buf[x+1][y+1] &= ~TILE_FLAG_CURSOR;t2buf[x+1][y+1] |= cflag;_update_single_grid(x, y);return oldc;}
}void StoreDungeonView(unsigned int *tileb){int x, y;int count = 0;if (tileb == NULL)tileb = tb_bk;for (y = 0; y < tile_dngn_y; y++){for (x = 0; x < tile_dngn_x; x++){tileb[count++] = t1buf[x+1][y+1];tileb[count++] = t2buf[x+1][y+1];}}}void LoadDungeonView(unsigned int *tileb){int x, y;int count = 0;if (tileb == NULL)tileb = tb_bk;for (y = 0; y < crawl_view.viewsz.y; y++){for (x = 0; x < crawl_view.viewsz.x; x++){if (tileb[count] == tileb[count+1])tileb[count] = 0;t1buf[x+1][y+1] = tileb[count++];t2buf[x+1][y+1] = tileb[count++];}}}//Draw the tile screen once and for allvoid TileDrawDungeon(unsigned int *tileb){if (!TileImg)return;ASSERT(tile_dngn_x == crawl_view.viewsz.x);ASSERT(tile_dngn_y == crawl_view.viewsz.y);ASSERT(tile_xmax = crawl_view.viewsz.x);ASSERT(tile_ymax = crawl_view.viewsz.y);LoadDungeonView(tileb);extern int tile_cursor_x;tile_cursor_x = -1;for (int x = 0; x < crawl_view.viewsz.x; x++)for (int y = 0; y < crawl_view.viewsz.y; y++)_tile_draw_grid(x, y);force_redraw_tile = false;TileDrawDungeonAux();region_tile->redraw();
#endif
void TileDrawFarDungeon(int cx, int cy){unsigned int tb[TILE_DAT_YMAX*TILE_DAT_XMAX*2];int count = 0;for (int y = 0; y < tile_dngn_y; y++){for (int x = 0; x < tile_dngn_x; x++){int fg;int bg;const coord_def gc(cx + x - tile_dngn_x/2,cy + y - tile_dngn_y/2);const coord_def ep = view2show(grid2view(gc));// mini "viewwindow" routineif (!map_bounds(gc)){fg = 0;bg = TILE_DNGN_UNSEEN;}else if (!crawl_view.in_grid_los(gc) || !env.show(ep)){fg = env.tile_bk_fg[gc.x][gc.y];bg = env.tile_bk_bg[gc.x][gc.y];if (bg == 0)bg |= TILE_DNGN_UNSEEN;bg |= tile_unseen_flag(gc);}else{fg = env.tile_fg[ep.x-1][ep.y-1];bg = env.tile_bg[ep.x-1][ep.y-1];}
if (gc.x == cx && gc.y == cy)bg |= TILE_FLAG_CURSOR1;tb[count++] = fg;tb[count++] = bg;}}tile_finish_dngn(tb, cx, cy);TileDrawDungeon(tb);region_tile->redraw();}void TileDrawMap(int gx, int gy){TileDrawFarDungeon(gx, gy);}// Load optional wall tilestatic void _TileLoadWallAux(int idx_src, int idx_dst, img_type wall){int tile_per_row = ImgWidth(wall) / TILE_X;int sx = idx_src % tile_per_row;int sy = idx_src / tile_per_row;sx *= TILE_X;sy *= TILE_Y;_ImgCopyToTileImg(idx_dst, wall, sx, sy, 1);}
floor_tile_idx = TILE_DNGN_FLOOR;floor_flavors = tile_W2D_count[floor_idx];int offset = floor_tile_idx;for (int i = 0; i < floor_flavors; i++){int idx_src = tile_W2D_start[floor_idx] + i;int idx_dst = offset++;_TileLoadWallAux(idx_src, idx_dst, WallImg);}
// TODO enne - link floor tile index to the right location rather than// starting at floor normalfloor_tile_idx = tile_DNGN_start[floor_idx];floor_flavors = tile_DNGN_count[floor_idx];
wall_tile_idx = offset;wall_flavors = tile_W2D_count[wall_idx];for (int i = 0; i < wall_flavors; i++){int idx_src = tile_W2D_start[wall_idx] + i;int idx_dst = offset++;_TileLoadWallAux(idx_src, idx_dst, WallImg);}
wall_tile_idx = tile_DNGN_start[wall_idx];wall_flavors = tile_DNGN_count[wall_idx];
special_tile_idx = offset;special_flavors = tile_W2D_count[special_idx];for (int i = 0; i < special_flavors; i++){int idx_src = tile_W2D_start[special_idx] + i;int idx_dst = offset++;_TileLoadWallAux(idx_src, idx_dst, WallImg);}
special_tile_idx = tile_DNGN_start[special_idx];special_flavors = tile_DNGN_count[special_idx];
static int current_parts[TILEP_PARTS_TOTAL];static bool _draw_doll(img_type img, dolls_data *doll, bool force_redraw = false,bool your_doll = true){const int p_order[TILEP_PARTS_TOTAL] ={TILEP_PART_SHADOW,TILEP_PART_HALO,TILEP_PART_DRCWING,TILEP_PART_CLOAK,TILEP_PART_BASE,TILEP_PART_BOOTS,TILEP_PART_LEG,TILEP_PART_BODY,TILEP_PART_ARM,TILEP_PART_HAND1,TILEP_PART_HAND2,TILEP_PART_HAIR,TILEP_PART_BEARD,TILEP_PART_HELM,TILEP_PART_DRCHEAD};int p_order2[TILEP_PARTS_TOTAL];int i;int flags[TILEP_PARTS_TOTAL];int parts2[TILEP_PARTS_TOTAL];int *parts = doll->parts;int c = 1;bool changed = false;int default_parts[TILEP_PARTS_TOTAL];memset(default_parts, 0, sizeof(default_parts));if (your_doll){tilep_race_default(you.species, parts[TILEP_PART_BASE] % 2,you.experience_level, default_parts);if (default_parts[TILEP_PART_BASE] != parts[TILEP_PART_BASE])force_redraw = true;parts[TILEP_PART_BASE] = default_parts[TILEP_PART_BASE];// TODO enne - make these configurable.parts[TILEP_PART_DRCHEAD] = default_parts[TILEP_PART_DRCHEAD];parts[TILEP_PART_DRCWING] = default_parts[TILEP_PART_DRCWING];bool halo = inside_halo(you.x_pos, you.y_pos);parts[TILEP_PART_HALO] = halo ? TILEP_HALO_TSO : 0;}
// convert TILEP_SHOW_EQUIP into real parts numberfor (i = 0; i < TILEP_PARTS_TOTAL; i++){parts2[i] = parts[i];if (parts2[i] == TILEP_SHOW_EQUIP){int item = -1;switch (i){case TILEP_PART_HAND1:item = you.equip[EQ_WEAPON];if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)parts2[i] = TILEP_HAND1_BLADEHAND;else if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_weapon(you.inv[item]);break;case TILEP_PART_HAND2:item = you.equip[EQ_SHIELD];if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)parts2[i] = TILEP_HAND2_BLADEHAND;else if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_shield(you.inv[item]);break;case TILEP_PART_BODY:item = you.equip[EQ_BODY_ARMOUR];if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_armour(you.inv[item]);break;case TILEP_PART_CLOAK:item = you.equip[EQ_CLOAK];if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_cloak(you.inv[item]);break;case TILEP_PART_HELM:item = you.equip[EQ_HELMET];if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_helm(you.inv[item]);if (parts2[i] == 0 && player_mutation_level(MUT_HORNS) > 0){switch (player_mutation_level(MUT_HORNS)){case 1:parts2[i] = TILEP_HELM_HORNS1;break;case 2:parts2[i] = TILEP_HELM_HORNS2;break;case 3:parts2[i] = TILEP_HELM_HORNS3;break;}}break;case TILEP_PART_BOOTS:item = you.equip[EQ_BOOTS];if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_boots(you.inv[item]);if (parts2[i] == 0 && player_mutation_level(MUT_HOOVES))parts2[i] = TILEP_BOOTS_HOOVES;break;case TILEP_PART_ARM:item = you.equip[EQ_GLOVES];if (item == -1)parts2[i] = 0;elseparts2[i] = tilep_equ_gloves(you.inv[item]);// There is player_has_claws() but it is not equivalent.// Claws appear if they're big enough to not wear gloves// or on races that have claws.if (parts2[i] == 0 && (player_mutation_level(MUT_CLAWS) >= 3|| you.species == SP_TROLL || you.species == SP_GHOUL)){parts2[i] = TILEP_ARM_CLAWS;}break;case TILEP_PART_HAIR:case TILEP_PART_BEARD:parts2[i] = default_parts[i];break;case TILEP_PART_LEG:default:parts2[i] = 0;}}if (parts2[i] != current_parts[i])changed = true;current_parts[i] = parts2[i];}if (!changed && !force_redraw)return (false);tilep_calc_flags(parts2, flags);ImgClear(img);// Hack: change overlay order of boots/skirts.for (i = 0; i < TILEP_PARTS_TOTAL; i++)p_order2[i] = p_order[i];// Swap boot and leg-armour.if (parts2[TILEP_PART_LEG] < TILEP_LEG_SKIRT_OFS){p_order2[6] = TILEP_PART_LEG;p_order2[5] = TILEP_PART_BOOTS;}for (i = 0; i < TILEP_PARTS_TOTAL; i++){int p = p_order2[i];int ymax = TILE_Y;if (flags[p] == TILEP_FLAG_CUT_CENTAUR|| flags[p] == TILEP_FLAG_CUT_NAGA){ymax=18;}if (parts2[p] && p == TILEP_PART_BOOTS&& (parts2[p] == TILEP_BOOTS_NAGA_BARDING|| parts2[p] == TILEP_BOOTS_CENTAUR_BARDING)){// Special case for barding. They should be in "boots" but because// they're double-wide, they're stored in a different part. We just// intercept it here before drawing.char tile = (parts2[p] == TILEP_BOOTS_NAGA_BARDING) ?TILEP_SHADOW_NAGA_BARDING :TILEP_SHADOW_CENTAUR_BARDING;_tcache_overlay_player(img, 0, 0, TILEP_PART_SHADOW,tile, TILE_Y, &c);}else if (parts2[p] && flags[p])_tcache_overlay_player(img, 0, 0, p, parts2[p], ymax, &c);}return (true);}
}void TilePlayerRefresh(){if (!_draw_doll(DollCacheImg, ¤t_doll))return; // Not changed_ImgCopyToTileImg(TILE_PLAYER, DollCacheImg, 0, 0, 1);_redraw_spx_tcache(TILE_PLAYER);force_redraw_tile = true;const coord_def ep = grid2view(you.pos());_update_single_grid(ep.x-1, ep.y-1);
#endif
void TilePlayerInit(){int i;int cur_doll = 0;int mode = TILEP_M_DEFAULT;dolls_data doll;int gender = 0;for (i = 0; i < TILEP_PARTS_TOTAL; i++)doll.parts[i] = 0;tilep_race_default(you.species, gender, you.experience_level, doll.parts);tilep_job_default(you.char_class, gender, doll.parts);_load_doll_data("dolls.txt", &doll, 1, &mode, &cur_doll);current_doll = doll;_draw_doll(DollCacheImg, &doll);_ImgCopyToTileImg(TILE_PLAYER, DollCacheImg, 0, 0, 1);}
}void TileInitItems(){for (int i = 0; i < NUM_POTIONS; i++){int special = you.item_description[IDESC_POTIONS][i];int tile0 = TILE_POTION_OFFSET + special % 14;int tile1 = TILE_POT_HEALING + i;_ImgCopyFromTileImg(tile0, DollCacheImg, 0, 0, 1);_ImgCopyFromTileImg(tile1, DollCacheImg, 0, 0, 0);_ImgCopyToTileImg(tile1, DollCacheImg, 0, 0, 1);}for (int i = 0; i < NUM_WANDS; i++){int special = you.item_description[IDESC_WANDS][i];int tile0 = TILE_WAND_OFFSET + special % 12;int tile1 = TILE_WAND_FLAME + i;_ImgCopyFromTileImg(tile0, DollCacheImg, 0, 0, 1);_ImgCopyFromTileImg(tile1, DollCacheImg, 0, 0, 0);_ImgCopyToTileImg(tile1, DollCacheImg, 0, 0, 1);}for (int i = 0; i < STAFF_SMITING; i++){int special = you.item_description[IDESC_STAVES][i];int tile0 = TILE_STAFF_OFFSET + (special / 4) % 10;int tile1 = TILE_STAFF_WIZARDRY + i;_ImgCopyFromTileImg(tile0, DollCacheImg, 0, 0, 1);_ImgCopyFromTileImg(tile1, DollCacheImg, 0, 0, 0);_ImgCopyToTileImg(tile1, DollCacheImg, 0, 0, 1);}for (int i = STAFF_SMITING; i < NUM_STAVES; i++){int special = you.item_description[IDESC_STAVES][i];int tile0 = TILE_ROD_OFFSET + (special / 4) % 10;int tile1 = TILE_ROD_SMITING + i - STAFF_SMITING;_ImgCopyFromTileImg(tile0, DollCacheImg, 0, 0, 1);_ImgCopyFromTileImg(tile1, DollCacheImg, 0, 0, 0);_ImgCopyToTileImg(tile1, DollCacheImg, 0, 0, 1);}
#endif
// Monster weapon tile#define N_MCACHE (TILE_MCACHE_END - TILE_MCACHE_START +1)typedef struct mcache mcache;struct mcache{bool lock_flag;mcache *next;int mon_tile;int equ_tile;int draco;int idx;};mcache mc_data[N_MCACHE];
int handidx = hand == 1 ? TILEP_PART_HAND1 : TILEP_PART_HAND2;int nx = tilep_parts_nx[handidx];int ny = tilep_parts_ny[handidx];int ox = tilep_parts_ox[handidx];int oy = tilep_parts_oy[handidx];int wx = std::min(TILE_X/nx + ofs_x, TILE_X/nx);int wy = std::min(TILE_Y/ny + ofs_y, TILE_Y/ny);int idx = equ_tile -1;int tidx = tilep_parts_start[handidx] + idx/(nx*ny);//Source posint xs = (tidx % TILEP_PER_ROW)*TILE_X + (idx % nx) * (TILE_X/nx) - ofs_x;int ys = (tidx / TILEP_PER_ROW)*TILE_Y+ ((idx/nx) % ny) * (TILE_Y/ny) - ofs_y;
ofs_x = 0;ofs_y = 0;
ImgCopy(PlayerImg, xs, ys, wx, wy, DollCacheImg, ox, oy, 0);}static void _mcache_compose(int tile_idx, int mon_tile, int equ_tile){int ofs_x = 0;int ofs_y = 0;
// Copy monster tile_ImgCopyFromTileImg(mon_tile, DollCacheImg, 0, 0, 1);// Overlay weapon tile_ImgCopyDoll(equ_tile, 1, ofs_x, ofs_y);// In some cases, overlay a second weapon tile...if (mon_tile == TILE_MONS_DEEP_ELF_BLADEMASTER){int eq2;switch (equ_tile){case TILEP_HAND1_DAGGER:eq2 = TILEP_HAND2_DAGGER;break;case TILEP_HAND1_SABRE:eq2 = TILEP_HAND2_SABRE;break;default:case TILEP_HAND1_SHORT_SWORD_SLANT:eq2 = TILEP_HAND2_SHORT_SWORD_SLANT;break;};_ImgCopyDoll(eq2, 2, -ofs_x, ofs_y);}// Copy to the buffer_ImgCopyToTileImg(tile_idx, DollCacheImg, 0, 0, 1);_redraw_spx_tcache(tile_idx);
dolls_data doll;int x;int color = draconian_color(race, -1);int armour = 0;int armour2 = 0;int weapon = 0;int weapon2 = 0;int arm = 0;for (x = 0; x < TILEP_PARTS_TOTAL; x++){doll.parts[x] = 0;current_parts[x] = 0;}doll.parts[TILEP_PART_SHADOW] = 1;doll.parts[TILEP_PART_BASE] = TILEP_BASE_DRACONIAN + color *2;doll.parts[TILEP_PART_DRCWING] = 1 + color;doll.parts[TILEP_PART_DRCHEAD] = 1 + color;switch(cls){case MONS_DRACONIAN_CALLER:weapon = TILEP_HAND1_STAFF_EVIL;weapon2 = TILEP_HAND2_BOOK_YELLOW;armour = TILEP_BODY_ROBE_BROWN;break;case MONS_DRACONIAN_MONK:arm = TILEP_ARM_GLOVE_SHORT_BLUE;armour = TILEP_BODY_KARATE2;break;case MONS_DRACONIAN_ZEALOT:weapon = TILEP_HAND1_MACE;weapon2 = TILEP_HAND2_BOOK_CYAN;armour = TILEP_BODY_MONK_BLUE;break;case MONS_DRACONIAN_SHIFTER:weapon = TILEP_HAND1_STAFF_LARGE;armour = TILEP_BODY_ROBE_CYAN;weapon2 = TILEP_HAND2_BOOK_GREEN;break;case MONS_DRACONIAN_ANNIHILATOR:weapon = TILEP_HAND1_STAFF_RUBY;weapon2 = TILEP_HAND2_FIRE_CYAN;armour = TILEP_BODY_ROBE_GREEN_GOLD;break;case MONS_DRACONIAN_KNIGHT:weapon = w;weapon2 = TILEP_HAND2_SHIELD_KNIGHT_GRAY;armour = TILEP_BODY_BPLATE_METAL1;armour2 = TILEP_LEG_BELT_GRAY;break;case MONS_DRACONIAN_SCORCHER:weapon = TILEP_HAND1_FIRE_RED;weapon2 = TILEP_HAND2_BOOK_RED;armour = TILEP_BODY_ROBE_RED;break;default:weapon = w;armour = TILEP_BODY_BELT2;armour2 = TILEP_LEG_LOINCLOTH_RED;break;}doll.parts[TILEP_PART_HAND1] = weapon;doll.parts[TILEP_PART_HAND2] = weapon2;doll.parts[TILEP_PART_BODY] = armour;doll.parts[TILEP_PART_LEG] = armour2;doll.parts[TILEP_PART_ARM] = arm;ImgClear(DollCacheImg);_draw_doll(DollCacheImg, &doll, true, false);// Copy to the buffer_ImgCopyToTileImg(tile_idx, DollCacheImg, 0, 0, 1);_redraw_spx_tcache(tile_idx);}static void _mcache_init(){int i;for (i = 0; i < N_MCACHE; i++){mc_data[i].lock_flag = false;mc_data[i].next = NULL;if (i != N_MCACHE - 1)mc_data[i].next = &mc_data[i+1];mc_data[i].idx = TILE_MCACHE_START + i;mc_data[i].mon_tile = 0;mc_data[i].equ_tile = 0;mc_data[i].draco = 0;}mc_head = &mc_data[0];}int get_base_idx_from_mcache(int tile_idx){for (mcache *mc = mc_head; mc != NULL; mc = mc->next){if (mc->idx == tile_idx)return mc->mon_tile;}return tile_idx;}
}void TileMcacheUnlock(){int i;for (i = 0; i < N_MCACHE; i++)mc_data[i].lock_flag = false;}int TileMcacheFind(int mon_tile, int equ_tile, int draco){mcache *mc = mc_head;mcache *prev = NULL;mcache *empty = NULL;#ifdef DEBUG_DIAGNOSTICSint count = 0;char cache_info[40];#endifint best2 = -1;int best3 = -1;while (true){if (mon_tile == mc->mon_tile && equ_tile == mc->equ_tile&& draco == mc->draco){// match found// move cache to the head to reduce future search timeif (prev != NULL)prev->next = mc->next;if (mc != mc_head)mc->next = mc_head;mc_head = mc;// lock itmc->lock_flag=true;// return cache indexreturn mc->idx;}else if (draco != 0 && mon_tile == mc->mon_tile && draco == mc->draco)// second best for draconian: only weapon differbest2 = mc->idx;else if (draco != 0 && mon_tile == mc->mon_tile)// third best for draconian: only class matchesbest3 = mc->idx;if (!mc->lock_flag)empty = mc;if (mc->next == NULL)break;prev = mc;mc = mc->next;#ifdef DEBUG_DIAGNOSTICScount++;#endif} // while// cache image not found and no room do draw itif (empty == NULL){#ifdef DEBUG_DIAGNOSTICSsnprintf( cache_info, 39, "mcache (M %d, E %d) cache full",mon_tile, equ_tile);mpr(cache_info, MSGCH_DIAGNOSTICS );#endifif (best2 != -1)return best2;if (best3 != -1)return best3;if (draco != 0)return TILE_ERROR;elsereturn mon_tile;}mc = empty;#ifdef DEBUG_DIAGNOSTICSsnprintf( cache_info, 39, "mcache (M %d, E %d) newly composed",mon_tile, equ_tile);mpr(cache_info, MSGCH_DIAGNOSTICS );#endif// compose new imageif (draco != 0)// race, class, weapon_mcache_compose_draco(mc->idx, draco, mon_tile, equ_tile);else_mcache_compose(mc->idx, mon_tile, equ_tile);mc->mon_tile = mon_tile;mc->equ_tile = equ_tile;mc->draco = draco;// move cache to the head to reduce future search timeif (prev)prev->next = mc->next;if (mc != mc_head)mc->next = mc_head;mc_head = mc;mc->lock_flag = true;return mc->idx;
}static void _TilePutch(int c, img_type Dest, int dx, int dy){int tidx = TILE_CHAR00 + (c-32)/8;int tidx2 = c & 7;int sx = (tidx % TILE_PER_ROW)*TILE_X + (tidx2 % 4)*(TILE_X/4);int sy = (tidx / TILE_PER_ROW)*TILE_Y + (tidx2 / 4)*(TILE_Y/2);;ImgCopy(TileImg, sx, sy, TILE_X/4, TILE_Y/2,Dest, dx, dy, 0);}void TileRedrawInv(int region){TileRegionClass *r = (region == REGION_INV1) ? region_item:region_item2;r->flag = true;r->make_active();r->redraw();}void TileClearInv(int region){TileRegionClass *r = (region == REGION_INV1) ? region_item: region_item2;for (int i = 0; i < r->mx * r->my; i++){TileDrawOneItem(region, i, 0, -1, -1, -1,false, false, false, false, false);}last_cursor = -1;itemlist_n = 0;}void TileDrawOneItem(int region, int i, char key, int idx,int tile, int num, bool floor,bool select, bool equip, bool tried, bool cursed){ASSERT(idx >= -1 && idx < MAX_ITEMS);TileRegionClass *r = (region == REGION_INV1) ? region_item: region_item2;int item_x = r->mx;int dx = (i % item_x) * TILE_X;int dy = (i / item_x) * TILE_Y;if (tile == -1){_ImgCopyFromTileImg(TILE_DNGN_UNSEEN, r->backbuf, dx, dy, 1);return;}if (floor)_ImgCopyFromTileImg(TILE_DNGN_FLOOR, r->backbuf, dx, dy, 1);else_ImgCopyFromTileImg(TILE_ITEM_SLOT, r->backbuf, dx, dy, 1);if (equip){if (cursed)_ImgCopyFromTileImg(TILE_ITEM_SLOT_EQUIP_CURSED, r->backbuf,dx, dy, 0);else_ImgCopyFromTileImg(TILE_ITEM_SLOT_EQUIP, r->backbuf, dx, dy, 0);}else if (cursed)_ImgCopyFromTileImg(TILE_ITEM_SLOT_CURSED, r->backbuf, dx, dy, 0);if (select)_ImgCopyFromTileImg(TILE_RAY_MESH, r->backbuf, dx, dy, 0);if (itemlist_iflag[i] & TILEI_FLAG_CURSOR)_ImgCopyFromTileImg(TILE_CURSOR, r->backbuf, dx, dy, 0);// Item tile_ImgCopyFromTileImg(tile, r->backbuf, dx, dy, 0);// quantity/chargeif (num != -1){// If you have that many, who cares.if (num > 999)num = 999;const int offset_amount = TILE_X/4;int offset = 0;int help = num;int c100 = help/100;help -= c100*100;if (c100){_TilePutch('0' + c100, r->backbuf, dx+offset, dy);offset += offset_amount;}int c10 = help/10;if (c10 || c100){_TilePutch('0' + c10, r->backbuf, dx+offset, dy);offset += offset_amount;}int c1 = help % 10;_TilePutch('0' + c1, r->backbuf, dx+offset, dy);}// '?' markif (tried)_TilePutch('?', r->backbuf, dx, dy + TILE_Y/2);// record tile information as we draw it so that we can re-draw it at willitemlist[i] = tile;itemlist_num[i] = num;itemlist_key[i] = key;itemlist_idx[i] = idx;itemlist_iflag[i] = 0;if (floor)itemlist_iflag[i] |= TILEI_FLAG_FLOOR;if (tried)itemlist_iflag[i] |= TILEI_FLAG_TRIED;if (equip)itemlist_iflag[i] |= TILEI_FLAG_EQUIP;if (cursed)itemlist_iflag[i] |= TILEI_FLAG_CURSE;if (select)itemlist_iflag[i] |= TILEI_FLAG_SELECT;if (i >= itemlist_n)itemlist_n = i+1;
#endif
void TileDrawInvData(int n, int flag, int *tiles, int *num, int *idx,int *iflags){int i;TileRegionClass *r = (flag == REGION_INV1 ? region_item: region_item2);r->flag = true;last_cursor = -1;int old_itemlist_n = itemlist_n;itemlist_n = n;int item_x = r->mx;int item_y = r->my;for (i = 0; i < item_x * item_y; i++){if (i == MAX_ITEMLIST)break;int tile0 = (i >= n) ? -1 : tiles[i];int idx0 = (i >= n) ? -1 : idx[i];char key = (iflags[i] & TILEI_FLAG_FLOOR) ? 0: index_to_letter(idx[i]);if (flag == itemlist_flag&& tile0 == itemlist[i]&& num[i] == itemlist_num[i]&& key == itemlist_key[i]&& idx0 == itemlist_idx[i]&& iflags[i] == itemlist_iflag[i]&& !force_redraw_inv&& i < old_itemlist_n){continue;}
TileDrawOneItem(flag, i, key, idx0, tile0, num[i],((iflags[i]&TILEI_FLAG_FLOOR) != 0),((iflags[i]&TILEI_FLAG_SELECT) != 0),((iflags[i]&TILEI_FLAG_EQUIP) != 0),((iflags[i]&TILEI_FLAG_TRIED) != 0),((iflags[i]&TILEI_FLAG_CURSE) != 0));}r->make_active();r->redraw();itemlist_flag = flag;force_redraw_inv = false;}void TileDrawInvCursor(int ix, bool flag){TileRegionClass *r =(itemlist_flag == REGION_INV1) ? region_item: region_item2;int tile0 = itemlist[ix];int num0 = itemlist_num[ix];if (flag)itemlist_iflag[ix] |= TILEI_FLAG_CURSOR;elseitemlist_iflag[ix] &= ~TILEI_FLAG_CURSOR;TileDrawOneItem(itemlist_flag, ix, itemlist_key[ix], itemlist_idx[ix], tile0, num0,((itemlist_iflag[ix]&TILEI_FLAG_FLOOR) != 0),((itemlist_iflag[ix]&TILEI_FLAG_SELECT) != 0),((itemlist_iflag[ix]&TILEI_FLAG_EQUIP) != 0),((itemlist_iflag[ix]&TILEI_FLAG_TRIED) != 0),((itemlist_iflag[ix]&TILEI_FLAG_CURSE) != 0));r->redraw();}void TileMoveInvCursor(int ix){if (last_cursor != -1)TileDrawInvCursor(last_cursor, false);if (ix != -1)TileDrawInvCursor(ix, true);last_cursor = ix;}int TileInvIdx(int i){if (i >= itemlist_n)return -1;elsereturn itemlist_idx[i];}
marshallByte(th, env.tile_flavor[count_x][count_y].wall);marshallByte(th, env.tile_flavor[count_x][count_y].floor);marshallByte(th, env.tile_flavor[count_x][count_y].special);
marshallByte(th, env.tile_flv[count_x][count_y].wall);marshallByte(th, env.tile_flv[count_x][count_y].floor);marshallByte(th, env.tile_flv[count_x][count_y].special);
env.tile_flavor[x][y].wall = unmarshallByte(th);env.tile_flavor[x][y].floor = unmarshallByte(th);env.tile_flavor[x][y].special = unmarshallByte(th);
env.tile_flv[x][y].wall = unmarshallByte(th);env.tile_flv[x][y].floor = unmarshallByte(th);env.tile_flv[x][y].special = unmarshallByte(th);
%sdir dc-dngnblank BLANKdngn_unseen DNGN_UNSEENfloor/pebble_gray0 DNGN_FLOORfloor/pebble_gray1floor/pebble_gray2floor/pebble_gray3floor/pebble_gray3floor/pebble_gray3floor/pebble_gray3floor/pebble_gray3 DNGN_FLOOR_SPECIALwall/brick_brown0 DNGN_ROCK_WALL_OFSwall/brick_brown1wall/brick_brown2wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3wall/brick_brown3floor/lava0 DNGN_LAVAfloor/lava1floor/lava2floor/lava3dngn_deep_water DNGN_DEEP_WATERdngn_deep_waterdngn_deep_waterdngn_deep_waterdngn_shallow_water DNGN_SHALLOW_WATERdngn_shallow_waterdngn_shallow_waterdngn_shallow_waterwall/stone2_gray0 DNGN_STONE_WALLwall/stone2_gray1wall/stone2_gray2wall/stone2_gray3dngn_metal_wall DNGN_METAL_WALLdngn_green_crystal_wall DNGN_GREEN_CRYSTAL_WALLdngn_wax_wall DNGN_WAX_WALL#dngn_rock_wall_00 DNGN_ROCK_WALL_OFS#dngn_rock_wall_01 IGNORE_COMMENT#dngn_rock_wall_02 IGNORE_COMMENT#dngn_rock_wall_03 IGNORE_COMMENT#dngn_rock_wall_04 IGNORE_COMMENT#dngn_rock_wall_05 IGNORE_COMMENT#dngn_rock_wall_06 IGNORE_COMMENT#dngn_rock_wall_07 IGNORE_COMMENT#dngn_rock_wall_08 IGNORE_COMMENT#dngn_rock_wall_09 IGNORE_COMMENT#dngn_rock_wall_10 IGNORE_COMMENT#dngn_rock_wall_11 IGNORE_COMMENT#dngn_rock_wall_12 IGNORE_COMMENT#dngn_rock_wall_13 IGNORE_COMMENT#dngn_rock_wall_14 IGNORE_COMMENT#dngn_rock_wall_15 IGNORE_COMMENT#dngn_stone_wall DNGN_STONE_WALLdngn_closed_door DNGN_CLOSED_DOORdngn_open_door DNGN_OPEN_DOOR###dc/wal8 DNGN_SECRET_DOORdngn_orcish_idol DNGN_ORCISH_IDOLdngn_silver_statue DNGN_SILVER_STATUEdngn_granite_statue DNGN_GRANITE_STATUEdngn_orange_crystal_statue DNGN_ORANGE_CRYSTAL_STATUEdngn_ice_statue DNGN_ICE_STATUE###dc/wal1 DNGN_PERMAROCK_WALL###dc/wal1 DNGN_LAST_SOLID_TILEdngn_enter_hell DNGN_ENTER_HELLdngn_branch_stairs DNGN_BRANCH_STAIRSdngn_trap_shaft DNGN_TRAP_SHAFT###847 DNGN_UNDISCOVERED_TRAPstone_stairs_down DNGN_STONE_STAIRS_DOWN#nh-dngn/staircase_down DNGN_STONE_STAIRS_DOWN_II#nh-dngn/staircase_down DNGN_STONE_STAIRS_DOWN_IIIrock_stairs_down DNGN_ROCK_STAIRS_DOWNstone_stairs_up DNGN_STONE_STAIRS_UP#nh-dngn/staircase_up DNGN_STONE_STAIRS_UP_II#nh-dngn/staircase_up DNGN_STONE_STAIRS_UP_IIIrock_stairs_up DNGN_ROCK_STAIRS_UPdngn_enter_shop DNGN_ENTER_SHOPdngn_enter_labyrinth DNGN_ENTER_LABYRINTHdngn_enter_dis DNGN_ENTER_DISdngn_enter_gehenna DNGN_ENTER_GEHENNAdngn_enter_cocytus DNGN_ENTER_COCYTUSdngn_enter_tartarus DNGN_ENTER_TARTARUSdngn_enter_abyss DNGN_ENTER_ABYSSdngn_exit DNGN_EXIT_ABYSSdngn_stone_arch DNGN_STONE_ARCHdngn_enter_pandemonium DNGN_ENTER_PANDEMONIUMdngn_exit DNGN_EXIT_PANDEMONIUMdngn_transit_pandemonium DNGN_TRANSIT_PANDEMONIUM####846 DNGN_BUILDER_SPECIAL_WALL####846 DNGN_BUILDER_SPECIAL_FLOORdngn_enter DNGN_ENTER#851 DNGN_ENTER_ORCISH_MINES#851 DNGN_ENTER_HIVE#851 DNGN_ENTER_LAIR#851 DNGN_ENTER_SLIME_PITS#851 DNGN_ENTER_VAULTS#851 DNGN_ENTER_CRYPT#851 DNGN_ENTER_HALL_OF_BLADES#851 DNGN_ENTER_ZOT#851 DNGN_ENTER_TEMPLE#851 DNGN_ENTER_SNAKE_PIT#851 DNGN_ENTER_ELVEN_HALLS#851 DNGN_ENTER_TOMB#851 DNGN_ENTER_SWAMPdngn_return DNGN_RETURN#850 DNGN_RETURN_FROM_ORCISH_MINES#850 DNGN_RETURN_FROM_HIVE#850 DNGN_RETURN_FROM_LAIR#850 DNGN_RETURN_FROM_SLIME_PITS#850 DNGN_RETURN_FROM_VAULTS#850 DNGN_RETURN_FROM_CRYPT#850 DNGN_RETURN_FROM_HALL_OF_BLADES#850 DNGN_RETURN_FROM_ZOT#850 DNGN_RETURN_FROM_TEMPLE#850 DNGN_RETURN_FROM_SNAKE_PIT#850 DNGN_RETURN_FROM_ELVEN_HALLS#850 DNGN_RETURN_FROM_TOMB#850 DNGN_RETURN_FROM_SWAMPdngn_altar_zin DNGN_ALTAR_ZINdngn_altar_shining_one DNGN_ALTAR_SHINING_ONEdngn_altar_kikubaaqudgha DNGN_ALTAR_KIKUBAAQUDGHAdngn_altar_yredelemnul DNGN_ALTAR_YREDELEMNULdngn_altar_xom DNGN_ALTAR_XOMdngn_altar_vehumet DNGN_ALTAR_VEHUMETdngn_altar_okawaru DNGN_ALTAR_OKAWARUdngn_altar_makhleb DNGN_ALTAR_MAKHLEBdngn_altar_sif_muna DNGN_ALTAR_SIF_MUNAdngn_altar_trog DNGN_ALTAR_TROGdngn_altar_nemelex_xobeh DNGN_ALTAR_NEMELEX_XOBEHdngn_altar_elyvilon DNGN_ALTAR_ELYVILONdngn_altar_lugonu DNGN_ALTAR_LUGONUdngn_altar_beogh DNGN_ALTAR_BEOGHdngn_blue_fountain DNGN_BLUE_FOUNTAINdngn_sparkling_fountain DNGN_SPARKLING_FOUNTAIN#858 DNGN_PERMADRY_FOUNTAINdngn_blood_fountain DNGN_BLOOD_FOUNTAINdngn_dry_fountain DNGN_DRY_FOUNTAIN%rim 0%rim 1%rim 0%rim 1dngn_trap_dart DNGN_TRAP_DARTdngn_trap_arrow DNGN_TRAP_ARROWdngn_trap_spear DNGN_TRAP_SPEARdngn_trap_axe DNGN_TRAP_AXEdngn_trap_teleport DNGN_TRAP_TELEPORTdngn_trap_alarm DNGN_TRAP_ALARMdngn_trap_blade DNGN_TRAP_BLADEdngn_trap_bolt DNGN_TRAP_BOLTdngn_trap_net DNGN_TRAP_NETdngn_trap_zot DNGN_TRAP_ZOTdngn_trap_needle DNGN_TRAP_NEEDLE%rim 0%rim 1gate_open_left DNGN_GATE_OPEN_LEFTgate_open_middle DNGN_GATE_OPEN_MIDDLEgate_open_right DNGN_GATE_OPEN_RIGHTgate_closed_left DNGN_GATE_CLOSED_LEFTgate_closed_middle DNGN_GATE_CLOSED_MIDDLEgate_closed_right DNGN_GATE_CLOSED_RIGHTdngn_transparent_wall DNGN_TRANSPARENT_WALLfloor/floor_nerves0 DNGN_FLOOR_CORRUPTfloor/floor_nerves1floor/floor_nerves2floor/floor_nerves3wall/undead0 DNGN_WALL_CORRUPTwall/undead1wall/undead2wall/undead3# Do not separate basic floors and rock walls. They get overwritten by# branch-specific floors and walls and will overwrite anything in between.
counts[tilecountidx++] = tilecount;
fprintf(sfp, "\n\n");fprintf(sfp, "enum TILE_%sCOUNT_IDX {\n", enumprefix);for (i = 0; i < tilecountidx; i++){fprintf(sfp, " IDX_%s,\n", countnames[i]);}fprintf(sfp, " IDX_%sTOTAL\n};\n\n", enumprefix);fprintf(sfp, "extern int tile_%scount[IDX_%sTOTAL];\n", enumprefix, enumprefix);fprintf(sfp, "extern int tile_%sstart[IDX_%sTOTAL];\n\n", enumprefix, enumprefix);
%enumprefix W2D_%tiledef tiledef-w2d.h%tilecount tilecount-w2d.h%width 16%back none%name wall2d%sdir dc-dngnwall/brick_brown0 WALL_NORMALwall/brick_brown1wall/brick_brown2wall/brick_brown3floor/pebble_gray0 FLOOR_NORMALfloor/pebble_gray1floor/pebble_gray2floor/pebble_gray3floor/pebble_gray4wall/relief0 WALL_HALLwall/relief1wall/relief2wall/relief3floor/mesh0 FLOOR_HALLfloor/mesh1floor/mesh2floor/mesh3wall/hive0 WALL_HIVEwall/hive1wall/hive2wall/hive3floor/hive0 FLOOR_HIVEfloor/hive1floor/hive2floor/hive3wall/ice0 WALL_ICEwall/ice1wall/ice2wall/ice3floor/ice0 FLOOR_ICEfloor/ice1floor/ice2floor/ice3wall/lair0 WALL_LAIRwall/lair1wall/lair2wall/lair3floor/lair0 FLOOR_LAIRfloor/lair1floor/lair2floor/lair3## orcs don't have their own floor or walls yet...wall/lair0 WALL_ORCwall/lair1wall/lair2wall/lair3floor/hive0 FLOOR_ORCfloor/hive1floor/hive2floor/hive3wall/slime0 WALL_SLIMEwall/slime1wall/slime2wall/slime3floor/bog_green0 FLOOR_SLIMEfloor/bog_green1floor/bog_green2floor/bog_green3wall/snake0 WALL_SNAKEwall/snake1wall/snake2wall/snake3floor/snake0 FLOOR_SNAKEfloor/snake1floor/snake2floor/snake3## swamp also doesn't have any unique walls...wall/lair0 WALL_SWAMPwall/lair1wall/lair2wall/lair3floor/swamp0 FLOOR_SWAMPfloor/swamp1floor/swamp2floor/swamp3wall/tomb0 WALL_TOMBwall/tomb1wall/tomb2wall/tomb3floor/tomb0 FLOOR_TOMBfloor/tomb1floor/tomb2floor/tomb3wall/undead0 WALL_UNDEADwall/undead1wall/undead2wall/undead3floor/tomb0 FLOOR_UNDEADfloor/tomb1floor/tomb2floor/tomb3wall/vault0 WALL_VAULTwall/vault1wall/vault2wall/vault3floor/rect_gray0 FLOOR_VAULTfloor/rect_gray1floor/rect_gray2floor/rect_gray3wall/zot_blue0 WALL_ZOT_BLUEwall/zot_blue1wall/zot_blue2wall/zot_blue3floor/tomb0 FLOOR_ZOT_BLUEfloor/tomb1floor/tomb2floor/tomb3wall/zot_cyan0 WALL_ZOT_CYANwall/zot_cyan1wall/zot_cyan2wall/zot_cyan3floor/tomb0 FLOOR_ZOT_CYANfloor/tomb1floor/tomb2floor/tomb3wall/zot_gray0 WALL_ZOT_GRAYwall/zot_gray1wall/zot_gray2wall/zot_gray3floor/tomb0 FLOOR_ZOT_GRAYfloor/tomb1floor/tomb2floor/tomb3wall/zot_green0 WALL_ZOT_GREENwall/zot_green1wall/zot_green2wall/zot_green3floor/tomb0 FLOOR_ZOT_GREENfloor/tomb1floor/tomb2floor/tomb3wall/zot_magenta0 WALL_ZOT_MAGENTAwall/zot_magenta1wall/zot_magenta2wall/zot_magenta3floor/tomb0 FLOOR_ZOT_MAGENTAfloor/tomb1floor/tomb2floor/tomb3wall/zot_red0 WALL_ZOT_REDwall/zot_red1wall/zot_red2wall/zot_red3floor/tomb0 FLOOR_ZOT_REDfloor/tomb1floor/tomb2floor/tomb3wall/zot_yellow0 WALL_ZOT_YELLOWwall/zot_yellow1wall/zot_yellow2wall/zot_yellow3floor/tomb0 FLOOR_ZOT_YELLOWfloor/tomb1floor/tomb2floor/tomb3wall/wall_flesh0 WALL_FLESHwall/wall_flesh1wall/wall_flesh2wall/wall_flesh3wall/wall_flesh4wall/wall_flesh5wall/wall_flesh6floor/floor_nerves0 FLOOR_NERVESfloor/floor_nerves1floor/floor_nerves2floor/floor_nerves3floor/floor_nerves4floor/floor_nerves5floor/floor_nerves6wall/wall_vines0 WALL_VINESwall/wall_vines1wall/wall_vines2wall/wall_vines3wall/wall_vines4wall/wall_vines5wall/wall_vines6floor/floor_vines0 FLOOR_VINESfloor/floor_vines1floor/floor_vines2floor/floor_vines3floor/floor_vines4floor/floor_vines5floor/floor_vines6wall/pebble_red0 WALL_PEBBLE_REDwall/pebble_red1wall/pebble_red2wall/pebble_red3floor/rough_red0 FLOOR_ROUGH_REDfloor/rough_red1floor/rough_red2floor/rough_red3floor/floor_sand_stone0 FLOOR_SAND_STONEfloor/floor_sand_stone1floor/floor_sand_stone2floor/floor_sand_stone3floor/floor_sand_stone4floor/floor_sand_stone5floor/floor_sand_stone6floor/floor_sand_stone7wall/wall_yellow_rock0 WALL_YELLOW_ROCKwall/wall_yellow_rock1wall/wall_yellow_rock2wall/wall_yellow_rock3wall/brick_gray0 WALL_BAZAAR_GRAYwall/brick_gray1wall/brick_gray2wall/brick_gray3wall/stone_gray0 WALL_BAZAAR_STONEwall/stone_gray1wall/stone_gray2wall/stone_gray3floor/grass0 FLOOR_BAZAAR_GRASSfloor/grass1floor/grass2floor/grass_n FLOOR_BAZAAR_GRASS1_SPECIALfloor/grass_nefloor/grass_efloor/grass_sefloor/grass_sfloor/grass_swfloor/grass_wfloor/grass_nwfloor/grass_full%start%compose floor/grass0%compose floor/pedestal_n%finish FLOOR_BAZAAR_GRASS2_SPECIAL%start%compose floor/grass1%compose floor/pedestal_ne%finish%start%compose floor/grass2%compose floor/pedestal_e%finish%start%compose floor/grass1%compose floor/pedestal_se%finish%start%compose floor/grass0%compose floor/pedestal_s%finish%start%compose floor/grass1%compose floor/pedestal_sw%finish%start%compose floor/grass2%compose floor/pedestal_w%finish%start%compose floor/grass0%compose floor/pedestal_nw%finishfloor/pedestal_full%start%compose floor/rect_gray0%compose floor/pedestal_n%finish FLOOR_BAZAAR_VAULT_SPECIAL%start%compose floor/rect_gray1%compose floor/pedestal_ne%finish%start%compose floor/rect_gray2%compose floor/pedestal_e%finish%start%compose floor/rect_gray3%compose floor/pedestal_se%finish%start%compose floor/rect_gray2%compose floor/pedestal_s%finish%start%compose floor/rect_gray1%compose floor/pedestal_sw%finish%start%compose floor/rect_gray0%compose floor/pedestal_w%finish%start%compose floor/rect_gray3%compose floor/pedestal_nw%finishfloor/pedestal_fullfloor/dirt0 FLOOR_BAZAAR_DIRTfloor/dirt1floor/dirt2floor/dirt_n FLOOR_BAZAAR_DIRT_SPECIALfloor/dirt_nefloor/dirt_efloor/dirt_sefloor/dirt_sfloor/dirt_swfloor/dirt_wfloor/dirt_nwfloor/dirt_full
%enumprefix DNGN_%tiledef tiledef-dngn.h%tilecount tilecount-dngn.h%width 16%back none%name dngn%sdir dc-dngndngn_unseen DNGN_UNSEENwall/brick_brown0 WALL_NORMALwall/brick_brown1wall/brick_brown2wall/brick_brown3floor/pebble_gray0 FLOOR_NORMALfloor/pebble_gray1floor/pebble_gray2floor/pebble_gray3floor/pebble_gray4wall/relief0 WALL_HALLwall/relief1wall/relief2wall/relief3floor/mesh0 FLOOR_HALLfloor/mesh1floor/mesh2floor/mesh3wall/hive0 WALL_HIVEwall/hive1wall/hive2wall/hive3floor/hive0 FLOOR_HIVEfloor/hive1floor/hive2floor/hive3wall/ice0 WALL_ICEwall/ice1wall/ice2wall/ice3floor/ice0 FLOOR_ICEfloor/ice1floor/ice2floor/ice3wall/lair0 WALL_LAIRwall/lair1wall/lair2wall/lair3floor/lair0 FLOOR_LAIRfloor/lair1floor/lair2floor/lair3## orcs don't have their own floor or walls yet...wall/lair0 WALL_ORCwall/lair1wall/lair2wall/lair3floor/hive0 FLOOR_ORCfloor/hive1floor/hive2floor/hive3wall/slime0 WALL_SLIMEwall/slime1wall/slime2wall/slime3floor/bog_green0 FLOOR_SLIMEfloor/bog_green1floor/bog_green2floor/bog_green3wall/snake0 WALL_SNAKEwall/snake1wall/snake2wall/snake3floor/snake0 FLOOR_SNAKEfloor/snake1floor/snake2floor/snake3## swamp also doesn't have any unique walls...wall/lair0 WALL_SWAMPwall/lair1wall/lair2wall/lair3floor/swamp0 FLOOR_SWAMPfloor/swamp1floor/swamp2floor/swamp3wall/tomb0 WALL_TOMBwall/tomb1wall/tomb2wall/tomb3floor/tomb0 FLOOR_TOMBfloor/tomb1floor/tomb2floor/tomb3wall/vault0 WALL_VAULTwall/vault1wall/vault2wall/vault3floor/rect_gray0 FLOOR_VAULTfloor/rect_gray1floor/rect_gray2floor/rect_gray3wall/zot_blue0 WALL_ZOT_BLUEwall/zot_blue1wall/zot_blue2wall/zot_blue3wall/zot_cyan0 WALL_ZOT_CYANwall/zot_cyan1wall/zot_cyan2wall/zot_cyan3wall/zot_gray0 WALL_ZOT_GRAYwall/zot_gray1wall/zot_gray2wall/zot_gray3wall/zot_green0 WALL_ZOT_GREENwall/zot_green1wall/zot_green2wall/zot_green3wall/zot_magenta0 WALL_ZOT_MAGENTAwall/zot_magenta1wall/zot_magenta2wall/zot_magenta3wall/zot_red0 WALL_ZOT_REDwall/zot_red1wall/zot_red2wall/zot_red3wall/zot_yellow0 WALL_ZOT_YELLOWwall/zot_yellow1wall/zot_yellow2wall/zot_yellow3wall/wall_flesh0 WALL_FLESHwall/wall_flesh1wall/wall_flesh2wall/wall_flesh3wall/wall_flesh4wall/wall_flesh5wall/wall_flesh6wall/wall_vines0 WALL_VINESwall/wall_vines1wall/wall_vines2wall/wall_vines3wall/wall_vines4wall/wall_vines5wall/wall_vines6floor/floor_vines0 FLOOR_VINESfloor/floor_vines1floor/floor_vines2floor/floor_vines3floor/floor_vines4floor/floor_vines5floor/floor_vines6wall/pebble_red0 WALL_PEBBLE_REDwall/pebble_red1wall/pebble_red2wall/pebble_red3floor/rough_red0 FLOOR_ROUGH_REDfloor/rough_red1floor/rough_red2floor/rough_red3floor/floor_sand_stone0 FLOOR_SAND_STONEfloor/floor_sand_stone1floor/floor_sand_stone2floor/floor_sand_stone3floor/floor_sand_stone4floor/floor_sand_stone5floor/floor_sand_stone6floor/floor_sand_stone7wall/wall_yellow_rock0 WALL_YELLOW_ROCKwall/wall_yellow_rock1wall/wall_yellow_rock2wall/wall_yellow_rock3wall/brick_gray0 WALL_BAZAAR_GRAYwall/brick_gray1wall/brick_gray2wall/brick_gray3wall/stone_gray0 WALL_BAZAAR_STONEwall/stone_gray1wall/stone_gray2wall/stone_gray3floor/grass0 FLOOR_BAZAAR_GRASSfloor/grass1floor/grass2floor/grass_n FLOOR_BAZAAR_GRASS1_SPECIALfloor/grass_nefloor/grass_efloor/grass_sefloor/grass_sfloor/grass_swfloor/grass_wfloor/grass_nwfloor/grass_full## NOTE: wall_undead and floor_nerves are used for the corruption effect.## They need to go last.wall/undead0 WALL_UNDEADwall/undead1wall/undead2wall/undead3floor/floor_nerves0 FLOOR_NERVESfloor/floor_nerves1floor/floor_nerves2floor/floor_nerves3floor/floor_nerves4floor/floor_nerves5floor/floor_nerves6%start%compose floor/grass0%compose floor/pedestal_n%finish FLOOR_BAZAAR_GRASS2_SPECIAL%start%compose floor/grass1%compose floor/pedestal_ne%finish%start%compose floor/grass2%compose floor/pedestal_e%finish%start%compose floor/grass1%compose floor/pedestal_se%finish%start%compose floor/grass0%compose floor/pedestal_s%finish%start%compose floor/grass1%compose floor/pedestal_sw%finish%start%compose floor/grass2%compose floor/pedestal_w%finish%start%compose floor/grass0%compose floor/pedestal_nw%finishfloor/pedestal_full%start%compose floor/rect_gray0%compose floor/pedestal_n%finish FLOOR_BAZAAR_VAULT_SPECIAL%start%compose floor/rect_gray1%compose floor/pedestal_ne%finish%start%compose floor/rect_gray2%compose floor/pedestal_e%finish%start%compose floor/rect_gray3%compose floor/pedestal_se%finish%start%compose floor/rect_gray2%compose floor/pedestal_s%finish%start%compose floor/rect_gray1%compose floor/pedestal_sw%finish%start%compose floor/rect_gray0%compose floor/pedestal_w%finish%start%compose floor/rect_gray3%compose floor/pedestal_nw%finishfloor/pedestal_fullfloor/dirt0 FLOOR_BAZAAR_DIRTfloor/dirt1floor/dirt2floor/dirt_n FLOOR_BAZAAR_DIRT_SPECIALfloor/dirt_nefloor/dirt_efloor/dirt_sefloor/dirt_sfloor/dirt_swfloor/dirt_wfloor/dirt_nwfloor/dirt_fullfloor/lava0 DNGN_LAVAfloor/lava1floor/lava2floor/lava3dngn_deep_water DNGN_DEEP_WATERdngn_deep_waterdngn_deep_waterdngn_deep_waterdngn_shallow_water DNGN_SHALLOW_WATERdngn_shallow_waterdngn_shallow_waterdngn_shallow_waterwall/stone2_gray0 DNGN_STONE_WALLwall/stone2_gray1wall/stone2_gray2wall/stone2_gray3dngn_metal_wall DNGN_METAL_WALLdngn_green_crystal_wall DNGN_GREEN_CRYSTAL_WALLdngn_wax_wall DNGN_WAX_WALLdngn_transparent_wall DNGN_TRANSPARENT_WALLdngn_closed_door DNGN_CLOSED_DOORgate_closed_left DNGN_GATE_CLOSED_LEFTgate_closed_middle DNGN_GATE_CLOSED_MIDDLEgate_closed_right DNGN_GATE_CLOSED_RIGHTdngn_open_door DNGN_OPEN_DOORgate_open_left DNGN_GATE_OPEN_LEFTgate_open_middle DNGN_GATE_OPEN_MIDDLEgate_open_right DNGN_GATE_OPEN_RIGHTdngn_orcish_idol DNGN_ORCISH_IDOLdngn_silver_statue DNGN_SILVER_STATUEdngn_granite_statue DNGN_GRANITE_STATUE%rim 1dngn_enter_hell DNGN_ENTER_HELL%rim 0dngn_branch_stairs DNGN_BRANCH_STAIRSdngn_trap_dart DNGN_TRAP_DARTdngn_trap_arrow DNGN_TRAP_ARROWdngn_trap_spear DNGN_TRAP_SPEARdngn_trap_axe DNGN_TRAP_AXEdngn_trap_teleport DNGN_TRAP_TELEPORTdngn_trap_alarm DNGN_TRAP_ALARMdngn_trap_blade DNGN_TRAP_BLADEdngn_trap_bolt DNGN_TRAP_BOLTdngn_trap_net DNGN_TRAP_NETdngn_trap_zot DNGN_TRAP_ZOTdngn_trap_needle DNGN_TRAP_NEEDLEdngn_trap_shaft DNGN_TRAP_SHAFTstone_stairs_down DNGN_STONE_STAIRS_DOWNrock_stairs_down DNGN_ROCK_STAIRS_DOWNstone_stairs_up DNGN_STONE_STAIRS_UProck_stairs_up DNGN_ROCK_STAIRS_UPdngn_enter_shop DNGN_ENTER_SHOPdngn_enter_labyrinth DNGN_ENTER_LABYRINTHdngn_enter_dis DNGN_ENTER_DISdngn_enter_gehenna DNGN_ENTER_GEHENNAdngn_enter_cocytus DNGN_ENTER_COCYTUSdngn_enter_tartarus DNGN_ENTER_TARTARUSdngn_enter_abyss DNGN_ENTER_ABYSSdngn_exit DNGN_EXIT_ABYSSdngn_stone_arch DNGN_STONE_ARCHdngn_enter_pandemonium DNGN_ENTER_PANDEMONIUMdngn_exit DNGN_EXIT_PANDEMONIUM%rim 1dngn_transit_pandemonium DNGN_TRANSIT_PANDEMONIUM%rim 0dngn_enter DNGN_ENTER%rim 1dngn_return DNGN_RETURN%rim 0dngn_altar_zin DNGN_ALTAR_ZINdngn_altar_shining_one DNGN_ALTAR_SHINING_ONEdngn_altar_kikubaaqudgha DNGN_ALTAR_KIKUBAAQUDGHAdngn_altar_yredelemnul DNGN_ALTAR_YREDELEMNULdngn_altar_xom DNGN_ALTAR_XOMdngn_altar_vehumet DNGN_ALTAR_VEHUMETdngn_altar_okawaru DNGN_ALTAR_OKAWARUdngn_altar_makhleb DNGN_ALTAR_MAKHLEBdngn_altar_sif_muna DNGN_ALTAR_SIF_MUNAdngn_altar_trog DNGN_ALTAR_TROGdngn_altar_nemelex_xobeh DNGN_ALTAR_NEMELEX_XOBEHdngn_altar_elyvilon DNGN_ALTAR_ELYVILONdngn_altar_lugonu DNGN_ALTAR_LUGONUdngn_altar_beogh DNGN_ALTAR_BEOGHdngn_blue_fountain DNGN_BLUE_FOUNTAINdngn_sparkling_fountain DNGN_SPARKLING_FOUNTAINdngn_blood_fountain DNGN_BLOOD_FOUNTAINdngn_dry_fountain DNGN_DRY_FOUNTAIN## Miscellaneous entries that get drawn on the backgrounddc-misc/blood_red BLOODdc-misc/blood_red1dc-misc/blood_red2dc-misc/blood_red3dc-misc/blood_red4dc-misc/halo HALOdc-misc/ray RAY_MESHdc-misc/travel_exclusion TRAVEL_EXCLUSION_BGdc-misc/travel_exclusion_centre TRAVEL_EXCLUSION_CENTRE_BGdc-misc/slot ITEM_SLOTeffect/sanctuary SANCTUARY
%sdir dc-dngndngn_orange_crystal_statue DNGN_ORANGE_CRYSTAL_STATUEdngn_ice_statue DNGN_ICE_STATUE%sdir dc-mon
dc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monsterdc-misc/unseen_monster
#ifdef USE_TILE// We could check for this above, but we need to do this post-move// to force the merfolk tile to be out of water.if ((!grid_is_water(new_grid) && grid_is_water(old_grid)|| grid_is_water(new_grid) && !grid_is_water(old_grid))&& you.species == SP_MERFOLK){TilePlayerRefresh();}#endif
FREETYPE_INCLUDE := -I/sw/include/freetype2# 10.5 Fink bugFINK_OPENGL_WORKAROUND := -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylibSDL_LDFLAGS += -framework Cocoa -L/usr/X11/lib $(FINK_OPENGL_WORKAROUND)EXTRA_INCLUDES += -I/sw/include
LIB = -static -lwinmm -mwindows -lcomctl32 -L$(LUASRC) -l$(LUALIB) -L$(SQLSRC) -l$(SQLLIB) -lpcreINCLUDES := -Iutil -I. -I$(LUASRC) -I$(SQLSRC)
LIB = -lwinmm -mwindows -lcomctl32 -L$(LUASRC) -l$(LUALIB) -L$(SQLSRC) -l$(SQLLIB) -lpng $(SDL_LDFLAGS) -lopengl32 -lglu32 -lSDL_image -lfreetypeINCLUDES := -Iutil -I. -I$(LUASRC) -I$(SQLSRC) $(EXTRA_INCLUDES)
mouse_mode mouse_control::ms_current_mode = MOUSE_MODE_NORMAL;
#ifdef USE_X11#include <X11/Xlib.h>#include <X11/X.h>#elif defined(WINDOWS)#include <windows.h>// windows.h defines 'near' as an empty string for compatibility.// This breaks the use of that as a variable name. Urgh.#ifdef near#undef near#endif#include <commdlg.h>#endif
void libgui_init();void libgui_shutdown();void edit_prefs();/* ***********************************************************************Minimap related* called from: misc view spells2* *********************************************************************** */void GmapInit(bool upd_tile);void GmapDisplay(int linex, int liney);void GmapUpdate(int x, int y, int what, bool upd_tile = true);
class mouse_control{public:mouse_control(int mode){oldmode = mouse_get_mode();mouse_set_mode(mode);}~mouse_control(){mouse_set_mode(oldmode);}private:int oldmode;};
enum InvAction{INV_DROP,INV_USE, // primary inventory useINV_USE2, // secondary inventory useINV_PICKUP,INV_VIEW,INV_USE_FLOOR,INV_EAT_FLOOR,INV_SELECT,INV_NUMACTIONS};void gui_get_mouse_inv(int &idx, InvAction &act);
void tile_place_cursor(int x, int y, bool display);void lock_region(int r);void unlock_region(int r);enum ScreenRegion{REGION_NONE,REGION_CRT,REGION_STAT, // stat areaREGION_MSG, // message areaREGION_MAP, // overview map areaREGION_DNGN,REGION_TDNGN,REGION_INV1, // items in inventoryREGION_INV2, // items in inventory?REGION_XMAP,REGION_TIP,NUM_REGIONS};
// types of events#define EV_KEYIN 1#define EV_MOVE 2#define EV_BUTTON 3#define EV_UNBUTTON 4#define _NORMALCURSOR 1#define _NOCURSOR 0
void clrscr();void message_out(int which_line, int colour, const char *s, int firstcol = 0, bool newline = true);void cgotoxy(int x, int y, int region = GOTO_CRT);void clear_message_window();void delay(int ms);void update_screen();int kbhit();
#define DCX (tile_dngn_x/2)#define DCY (tile_dngn_y/2)// libx11.cc or libwt.ccextern void update_tip_text(const char *tip);extern void libgui_init_sys();extern void libgui_shutdown_sys();extern void GetNextEvent(int *etype,int *key, bool *shift, bool *ctrl,int *x1, int *y1, int *x2, int *y2);#ifdef WIN32TILES// libwt.ccextern bool windows_change_font(char *font_name, int *font_size, bool dos);extern void windows_get_winpos(int *x, int *y);extern void TileInitWin();#endif// Main windowWinClass *win_main;// RegionsTextRegionClass *region_crt = NULL;MapRegionClass *region_map = NULL;TileRegionClass *region_tile = NULL;TextRegionClass *region_stat = NULL;TextRegionClass *region_msg = NULL;TextRegionClass *region_dngn = NULL;TextRegionClass *region_xmap = NULL;TextRegionClass *region_tip = NULL;TileRegionClass *region_item = NULL;TileRegionClass *region_item2 = NULL;// Raw tile imagesimg_type TileImg;img_type PlayerImg;img_type WallImg;// for item use gui#define MAX_ITEMLIST 60extern int itemlist[MAX_ITEMLIST];extern int itemlist_num[MAX_ITEMLIST];extern int itemlist_idx[MAX_ITEMLIST];extern char itemlist_key[MAX_ITEMLIST];extern int itemlist_iflag[MAX_ITEMLIST];extern int itemlist_flag;extern int itemlist_n;static bool gui_smart_cursor = false;// Window prefsstatic int crt_x = 80;static int crt_y = 30;static int map_px = 4;static int msg_x = 77, msg_y = 10;static int dngn_x = 19, dngn_y = 17;static int winox = 0, winoy = 0;#define MAX_PREF_CHAR 256#ifdef USE_X11#define UseDosChar falsestatic char font_name[MAX_PREF_CHAR+1] = "8x13";#endif#ifdef WIN32TILESstatic char font_name[MAX_PREF_CHAR+1] = "courier";#define UseDosChar (Options.use_dos_char)static char dos_font_name[MAX_PREF_CHAR+1] = "Terminal";static int dos_font_size = 16;#endifstatic int font_size = 12;
#define PREF_MODE_TILE 0#define PREF_MODE_NUM 1static const char *pref_mode_name[PREF_MODE_NUM] = { "Tile"};typedef struct prefs{const char *name;const char *tagname;char type;void *ptr;int min, max;int dummy_idx;}prefs;#ifdef WIN32TILES#define MAX_PREFS 11#else#define MAX_PREFS 9#endif#define MAX_EDIT_PREFS 5static int dummy_int[PREF_MODE_NUM][8];static char dummy_str[PREF_MODE_NUM][2][MAX_PREF_CHAR+1];struct prefs pref_data[MAX_PREFS] ={{"DUNGEON X", "DngnX", 'I', &dngn_x, 17, 35, 0},{"DUNGEON Y", "DngnY", 'I', &dngn_y, 17, 35, 1},{"MAP PX ", "MapPx", 'I', &map_px, 1, 10, 2},{"MSG X ", "MsgX", 'I', &msg_x, 40, 80, 3},{"MSG Y ", "MsgY", 'I', &msg_y, 8, 20, 4},{"WIN TOP ", "WindowTop", 'I', &winox, -100, 2000, 5},{"WIN LEFT ", "WindowLeft",'I', &winoy, -100, 2000, 6},{"FONT ", "FontName", 'S', font_name, 0, 0, 0},{"FONT SIZE", "FontSize", 'I', &font_size, 8, 24, 7}#ifdef WIN32TILES,{"DOS FONT", "DosFontName", 'S', dos_font_name, 0, 0, 1},{"DOS FONT SIZE", "DosFontSize", 'I', &dos_font_size, 8, 24, 8}#endif};static int pref_mode = 0;static void _libgui_load_prefs();static void _libgui_save_prefs();//Internal variablesstatic int mouse_mode = MOUSE_MODE_NORMAL;// Hack: prevent clrscr for some region.static bool region_lock[NUM_REGIONS];static bool toggle_telescope;/***********************************************************///micromap color array#define MAP_XMAX GXM#define MAP_YMAX GYMstatic unsigned char gmap_data[GXM][GYM];static int gmap_min_x, gmap_max_x;static int gmap_min_y, gmap_max_y;static int gmap_ox, gmap_oy;// Redefine color constants with shorter names to save space.#define PX_0 0#define PX_F 1#define PX_W 2#define PX_D 3#define PX_WB 4#define PX_I 5#define PX_M 6#define PX_US 7#define PX_DS 8#define PX_SS 9#define PX_WT 10#define PX_LV 11#define PX_T 12#define PX_MS 13static char _gmap_to_colour(char gm){switch (gm){case PX_0: // unseendefault:return Options.tile_unseen_col;case PX_F: // floorreturn Options.tile_floor_col;case PX_W: // wallsreturn Options.tile_wall_col;case PX_WB: // walls detected by Magic Mappingreturn Options.tile_mapped_wall_col;case PX_D: // doorsreturn Options.tile_door_col;case PX_I: // itemsreturn Options.tile_item_col;case PX_M: // (hostile) monstersreturn Options.tile_monster_col;case PX_US: // upstairsreturn Options.tile_upstairs_col;case PX_DS: // downstairsreturn Options.tile_downstairs_col;case PX_MS: // misc. features (altars, portals, fountains, ...)case PX_SS: // special stairs (?)return Options.tile_feature_col;case PX_WT: // waterreturn Options.tile_water_col;case PX_LV: // lavareturn Options.tile_lava_col;case PX_T: // trapsreturn Options.tile_trap_col;}}static const char gmap_col[256] = {/* 0x00 */ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0x08 */ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0x10 */ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0x18 */ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* ' ' '!' '"' '#' '$' '%' '&' ''' *//* 0x20 */ PX_0, PX_I, PX_I, PX_F, PX_I, PX_I, PX_M, PX_D,/* '(' ')' '*' '+' ',' '-' '.' '/' *//* 0x28 */ PX_I, PX_I, PX_WB,PX_I, PX_F, PX_0, PX_F, PX_I,/* 0 1 2 3 4 5 6 7 *//* 0x30 */ PX_0, PX_M, PX_M, PX_M, PX_M, PX_M, PX_0, PX_0,/* 8 9 : ; < = > ? *//* 0x38 */ PX_MS,PX_0, PX_0, PX_M, PX_US,PX_I, PX_DS,PX_I,/* @ A B C D E F G *//* 0x40 */ PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* H I J K L M N O *//* 0x48 */ PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* P Q R S T U V W *//* 0x50 */ PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* X Y Z [ \ ] ^ _ *//* 0x58 */ PX_M, PX_M, PX_M, PX_I, PX_I, PX_I, PX_T, PX_MS,/* ` a b c d e f g *//* 0x60 */ PX_0, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* h i j k l m n o *//* 0x68 */ PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* p q r s t u v w *//* 0x70 */ PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M, PX_M,/* x y z { | } ~ WALL *//* 0x78 */ PX_M, PX_M, PX_M, PX_WT,PX_0, PX_I, PX_I, PX_W,/* old cralwj symbols *//* �� �s �E �� �� �� �� �� *//* 0x80 */ PX_D, PX_SS,PX_F, PX_MS,PX_MS,PX_MS,PX_D, PX_WT,/* �t �� �� �� �� �� �� *//* 0x88 */ PX_SS,PX_W, PX_W, PX_W, PX_W, PX_LV, PX_I, PX_0,/**//* 0x90 144*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0x98 152*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xa0 160*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xa8 168*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xb0 176*/ PX_WB,PX_W, PX_W, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xb8 184*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xc0 192*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xc8 200*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xd0 208*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xd8 216*/ PX_0, PX_0, PX_0, PX_0, PX_MS, PX_0, PX_0, PX_0,/* 0xe0 224*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0,/* 0xe8 232*/ PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_0, PX_MS,/* 0xf0 240*/ PX_0, PX_0, PX_0, PX_0, PX_MS,PX_0, PX_0, PX_WT,/* 0xf8 248*/ PX_0, PX_F, PX_F, PX_0, PX_0, PX_0, PX_D, PX_0};int mouse_grid_x;int mouse_grid_y;bool mouse_in_dngn = false;static void _gui_set_mouse_view_pos(bool in_dngn, int cx, int cy){const coord_def& gc = view2grid(coord_def(cx,cy));mouse_grid_x = gc.x;mouse_grid_y = gc.y;ASSERT(!in_dngn || gc.x >= 0 && gc.y >= 0 && gc.x < GXM && gc.y < GYM);mouse_in_dngn = in_dngn;}bool gui_get_mouse_grid_pos(coord_def &gc){if (mouse_in_dngn){gc.x = mouse_grid_x;gc.y = mouse_grid_y;ASSERT(gc.x >= 0 && gc.y >= 0 && gc.x < GXM && gc.y < GYM);}return mouse_in_dngn;}int inv_idx = 0;InvAction inv_action = INV_NUMACTIONS;static void _gui_set_mouse_inv(int idx, InvAction act){inv_idx = idx;inv_action = act;}void gui_get_mouse_inv(int &idx, InvAction &act){idx = inv_idx;act = inv_action;}
void GmapUpdate(int x, int y, int what, bool upd_tile){// If you can't map the area, the minimap won't show.if (!player_in_mappable_area())return;int c;if (x == you.x_pos && y == you.y_pos)c = Options.tile_player_col; // Player position always highlighted.else{const coord_def gc(x,y);unsigned int feature = grd(gc);unsigned int grid_symbol;unsigned short grid_color;get_item_symbol(feature, &grid_symbol, &grid_color);switch (what){// In some cases (like smoke), update the gmap with the ground color// instead. This keeps it prettier in the case of lava + smoke.case '#':c = _gmap_to_colour(gmap_col[grid_symbol & 0xff]);break;default:c = _gmap_to_colour(gmap_col[what & 0xff]);break;}if (c == Options.tile_monster_col && mgrd[x][y] != NON_MONSTER){const int grid = mgrd[x][y];if (mons_friendly(&menv[grid]))c = Options.tile_friendly_col; // colour friendly monsterselse if (mons_neutral(&menv[grid]))c = Options.tile_neutral_col; // colour neutral monsterselse if (mons_class_flag(menv[grid].type, M_NO_EXP_GAIN))c = Options.tile_plant_col; // colour zero xp monsters}if (c == Options.tile_floor_col || c == Options.tile_item_col){if (is_exclude_root( coord_def(x,y) ))c = Options.tile_excl_centre_col;else if (c == Options.tile_floor_col && is_excluded(coord_def(x,y)))c = Options.tile_excluded_col;}}int oldc = gmap_data[x][y];gmap_data[x][y] = c;// NOTE: In the case of a magic mapping, we really want the// map to update with the correct feature (stone instead of rock wall,// fountains instead of TILE_ERROR). tileidx_unseen won't give that// to us. However, we can't give the player all the information,// since that might be cheating in some cases. This could be rewritten.int t = tile_idx_unseen_terrain(x, y, what);if (c != 0 && c!= oldc && upd_tile){if (c == PX_I || c == PX_M){env.tile_bk_bg[x][y] = t;if (env.tile_bk_bg[x][y] == 0)env.tile_bk_bg[x][y] = tileidx_feature(DNGN_UNSEEN, x, y);}else{env.tile_bk_bg[x][y] = t;}}else if (c == 0){// Forget map.env.tile_bk_fg[x][y] = 0;env.tile_bk_bg[x][y] = t;return;}if (x < gmap_min_x)gmap_min_x = x;else if (x > gmap_max_x)gmap_max_x = x;if (y < gmap_min_y)gmap_min_y = y;else if (y > gmap_max_y)gmap_max_y = y;}void GmapInit(bool upd_tile){// If you can't map the area, the minimap won't show.if (!player_in_mappable_area())return;int x, y;gmap_min_x = gmap_max_x = you.x_pos - 1;gmap_min_y = gmap_max_y = you.y_pos - 1;for (y = 0; y < GYM; y++)for (x = 0; x < GXM; x++)GmapUpdate(x, y, env.map[x][y].glyph(), upd_tile);}void GmapDisplay(int linex, int liney){static unsigned char buf2[GXM*GYM];int ox, oy;for (int x = 0; x < GXM*GYM; x++)buf2[x] = 0;if (!player_in_mappable_area()){// Don't bother in the Abyss or Labyrinth.region_map->flag = true;region_map->draw_data(buf2, false, 0, 0);return;}ox = ( gmap_min_x + (GXM - 1 - gmap_max_x) ) / 2;oy = ( gmap_min_y + (GYM - 1 - gmap_max_y) ) / 2;int count = ox + oy * GXM;gmap_ox = ox - gmap_min_x;gmap_oy = oy - gmap_min_y;for (int y = gmap_min_y; y <= gmap_max_y; y++){for (int x = gmap_min_x; x <= gmap_max_x; x++, count++)if (count >= 0 && count < GXM*GYM)buf2[count] = gmap_data[x][y];count += GXM - (gmap_max_x - gmap_min_x + 1);}// Highlight centre of the map (ox, oy).ox += linex - gmap_min_x;oy += liney - gmap_min_y;// [enne] Maybe we need another colour for the highlight?// [jpeg] I think reusing the player colour is okay, because that's// usually where the centre will be.buf2[ox + oy * GXM] = Options.tile_player_col;region_map->flag = true;region_map->draw_data(buf2, true, ox, oy);}// Initialize routines.static void _do_layout(){// buffer between map region and stat regionconst int map_stat_buffer = 5;#define LAYER_NML 0#define LAYER_CRT 1#define LAYER_XMAP 2win_main->wx = win_main->wy = 10;int tm = region_crt->dx;if (UseDosChar)win_main->placeRegion(region_xmap, LAYER_XMAP, 0, 0, tm, tm, tm, tm);RegionClass *lowest;// tile 2d modewin_main->placeRegion(region_tile, LAYER_NML, 0, 0);win_main->placeRegion(region_msg, LAYER_NML, region_tile, PLACE_BOTTOM,tm, tm, tm, tm);int sx = std::max(region_msg->ex + region_msg->dx, region_tile->ex)+ map_stat_buffer;int sy = 0;win_main->placeRegion(region_stat, LAYER_NML, sx, sy);win_main->placeRegion(region_map, LAYER_NML, region_stat, PLACE_BOTTOM);if (region_tip){win_main->placeRegion(region_tip, LAYER_NML, region_map, PLACE_BOTTOM);lowest = region_tip;}elselowest = region_map;int item_x = (win_main->wx-2*tm) / TILE_X;int item_y = (52 + item_x -1) / item_x;region_item2 -> resize(item_x, item_y, TILE_X, TILE_Y);// Update crt size appropriately, based on the window size.int crt_pwx = win_main->wx;int crt_wx = crt_pwx / region_crt->dx;int crt_pwy = win_main->wy - 2*tm - item_y * region_item2->dy;int crt_wy = crt_pwy / region_crt->dy;region_crt->resize(crt_wx, crt_wy);win_main->placeRegion(region_crt, LAYER_CRT, 0, 0, tm, tm, tm, tm);win_main->placeRegion(region_item2, LAYER_CRT, region_crt, PLACE_BOTTOM,tm, tm, tm, tm);if (Options.tile_show_items[0] != 0){item_x = (win_main->wx - lowest->sx) / TILE_X;item_y = (win_main->wy - lowest->ey) / TILE_Y;RegionClass *r0 = lowest;int place = PLACE_BOTTOM;int item_x2 = (win_main->wx - region_msg->ex) / TILE_X;int item_y2 = (win_main->wy - region_msg->sy) / TILE_Y;if (item_x * item_y < item_x2 * item_y2&& lowest->ey < region_msg->sy){item_x = item_x2;item_y = item_y2;r0 = region_msg;place = PLACE_RIGHT;}while (item_x * item_y < 40)item_y++;region_item -> resize(item_x, item_y, TILE_X, TILE_Y);win_main->placeRegion (region_item, LAYER_NML, r0, place);}}void libgui_init(){int i;int map_margin = 2;libgui_init_sys();for (i = 0; i < NUM_REGIONS; i++)region_lock[i] = false;pref_mode = PREF_MODE_TILE;_libgui_load_prefs();// Adjust sizes.if (dngn_x & 1 == 0) dngn_x++;if (dngn_y & 1 == 0) dngn_y++;if (font_size & 1 == 1) font_size--;tile_dngn_x = dngn_x;tile_dngn_y = dngn_y;/****************************************************/win_main = new WinClass();win_main->ox = winox;win_main->oy = winoy;region_crt = new TextRegionClass(crt_x, crt_y, 0, 0);region_crt->id = REGION_CRT;TextRegionClass::text_mode = region_crt;region_map =new MapRegionClass(MAP_XMAX+map_margin,MAP_YMAX+map_margin,map_margin, map_margin,2);region_map->id = REGION_MAP;region_map->dx = map_px;region_map->dy = map_px;TileInit();#ifdef WIN32TILESTileInitWin();#endifif (Options.tile_show_items[0] != 0){// temporal sizeregion_item = new TileRegionClass(1, 1, TILE_X, TILE_Y);region_item->id = REGION_INV1;}// temporal sizeregion_item2 = new TileRegionClass(1, 1, TILE_X, TILE_Y);region_item2->id = REGION_INV2;region_tile =new TileRegionClass(tile_dngn_x, tile_dngn_y,TILE_UX_NORMAL, TILE_UY_NORMAL);region_tile->id = REGION_DNGN;#if DEBUG_DIAGNOSTICS// One more line for debug GPS.region_stat = new TextRegionClass(crawl_view.hudsz.x,crawl_view.hudsz.y + 1, 0, 0);#elseregion_stat = new TextRegionClass(crawl_view.hudsz.x,crawl_view.hudsz.y, 0, 0);#endifregion_stat->id = REGION_STAT;region_msg = new TextRegionClass(msg_x, msg_y, 0, 0);region_msg->id = REGION_MSG;if (UseDosChar){region_xmap = new TextRegionClass(crt_x, crt_y, 0, 0);region_xmap->id = REGION_XMAP;}#ifdef WIN32TILESregion_crt->init_font(font_name, font_size);region_stat->copy_font(region_crt);region_msg->copy_font(region_crt);if (UseDosChar){region_xmap->dos_char = true;region_xmap->init_font(dos_font_name, dos_font_size);}#elif defined(USE_X11)const unsigned int region_tip_height = 3;region_tip = new TextRegionClass(region_stat->mx, region_tip_height, 0, 0);region_tip->id = REGION_TIP;region_crt->init_font(font_name);region_stat->init_font(font_name);region_msg->init_font(font_name);region_tip->init_font(font_name);if (region_dngn)region_dngn->init_font(font_name);#endif}void libgui_shutdown(){if (TileImg)ImgDestroy(TileImg);if (PlayerImg)ImgDestroy(PlayerImg);if (WallImg)ImgDestroy(WallImg);// Do this before delete win_main._libgui_save_prefs();std::vector<RegionClass *>::iterator r;for (r = win_main->regions.begin();r != win_main->regions.end();r++){RegionClass* pRegion = *r;delete (pRegion);}delete win_main;libgui_shutdown_sys();}// Save, Load, and Edit window prefs.static void _libgui_load_prefs(){int i, mode;FILE *fp;char buf[256];char tagbuf[256];// set defaultfor (mode = 0; mode < PREF_MODE_NUM; mode++){for (i = 0; i < MAX_PREFS; i++){struct prefs *p = &pref_data[i];int idx = p->dummy_idx;if (p->type == 'I')dummy_int[mode][idx] = *(int *)p->ptr;else if (p->type == 'S')strncpy(dummy_str[mode][idx], (char *)p->ptr, MAX_PREF_CHAR);}}const char *baseTxt = "wininit.txt";std::string winTxtString = datafile_path(baseTxt, false, true);const char *winTxt = (winTxtString.c_str()[0] == 0 ? baseTxt: winTxtString.c_str());if ( (fp = fopen(winTxt, "r")) != NULL ){while (!feof(fp)){fgets(buf, 250, fp);i = 0;while (buf[i] >= 32 && i < 120){i++;}buf[i] = 0;for (i = 0; i < MAX_PREFS; i++){struct prefs *p = &pref_data[i];for (mode = 0; mode < PREF_MODE_NUM; mode++){sprintf(tagbuf, "%s:%s", pref_mode_name[mode], p->tagname);if (strncmp(buf, tagbuf, strlen(tagbuf)) == 0){char *dat = &buf[strlen(tagbuf)+1];if (p->type == 'I'){int val = atoi(dat);if (val > p->max)val = p->max;if (val < p->min)val = p->min;dummy_int[mode][p->dummy_idx] = val;if (mode == pref_mode)*(int *)p->ptr = val;}else if (p->type == 'S'){strncpy(dummy_str[mode][p->dummy_idx], dat,MAX_PREF_CHAR);if (mode == pref_mode)strncpy((char *)p->ptr, dat, MAX_PREF_CHAR);}break;}}}} // while (!end of file)}}static void _libgui_save_prefs(){int i, mode;FILE *fp;if (!win_main)return;winox = win_main->ox;winoy = win_main->oy;#ifdef WIN32TILESwindows_get_winpos(&winox, &winoy);#endiffor (i = 0; i < MAX_PREFS; i++){struct prefs *p = &pref_data[i];int idx = p->dummy_idx;if (p->type == 'I')dummy_int[pref_mode][idx] = *(int *)p->ptr;else if (p->type == 'S')strncpy(dummy_str[pref_mode][idx], (char *)p->ptr, MAX_PREF_CHAR);}// Use the same directory as for macros.// (Yes, this is an arbitrary decision.)std::string dir = !Options.macro_dir.empty() ? Options.macro_dir :!SysEnv.crawl_dir.empty() ? SysEnv.crawl_dir : "";if (!dir.empty()){#ifndef DGL_MACRO_ABSOLUTE_PATHif (dir[dir.length() - 1] != FILE_SEPARATOR)dir += FILE_SEPARATOR;#endif}const char *baseTxt = "wininit.txt";std::string winTxtString = dir + baseTxt;if ( (fp = fopen(winTxtString.c_str(), "w")) == NULL )winTxtString = datafile_path(baseTxt, false, true);const char *winTxt = winTxtString.c_str()[0] == 0 ? baseTxt: winTxtString.c_str();if ( (fp = fopen(winTxt, "w")) != NULL ){for (mode = 0; mode < PREF_MODE_NUM; mode++){for (i = 0; i < MAX_PREFS; i++){struct prefs *p = &pref_data[i];int idx = p->dummy_idx;if (p->type == 'I'){fprintf(fp, "%s:%s=%d\n", pref_mode_name[mode],p->tagname, dummy_int[mode][idx]);}else if (p->type == 'S'){fprintf(fp, "%s:%s=%s\n", pref_mode_name[mode],p->tagname, dummy_str[mode][idx]);}}fprintf(fp, "\n");}fclose(fp);}}
}}void edit_prefs(){int i;int cur_pos = 0;cursor_control cs(false);bool need_draw_stat = true;bool need_draw_msg = true;if (region_tip)region_tip->clear();region_stat->clear();region_msg->clear();viewwindow(true, false);while (true){bool upd_msg = false;bool upd_dngn = false;bool upd_crt = false;bool upd_map = false;bool need_resize = false;int inc = 0;if (need_draw_msg){textcolor(LIGHTGREY);region_msg->clear();textcolor(WHITE);cgotoxy (4, 4, GOTO_MSG);cprintf("j, k, up, down : Select pref");cgotoxy (4, 5, GOTO_MSG);cprintf("h, l, left, right : Decrease/Increase");cgotoxy (4, 6, GOTO_MSG);cprintf("H, L : Dec/Inc by 10");need_draw_msg = false;}if (need_draw_stat){region_stat->clear();for (i = 0; i < MAX_EDIT_PREFS; i++){struct prefs *p = &pref_data[i];cgotoxy(2, i+2, GOTO_STAT);if (i == cur_pos){textcolor(0xf0);cprintf(">");}else{textcolor(LIGHTGREY);cprintf(" ");}if (pref_data[i].type == 'I')cprintf(" %s: %3d ", p->name, *(int *)p->ptr);elsecprintf(" %s: %s", p->name, (char *)p->ptr);}textcolor(LIGHTGREY);#ifdef WIN32TILEScgotoxy(4, MAX_EDIT_PREFS+3, GOTO_STAT);cprintf("FONT: %s %d",font_name, font_size);if (UseDosChar){cgotoxy(4, MAX_EDIT_PREFS+4, GOTO_STAT);cprintf("DOSFONT: %s %d", dos_font_name, dos_font_size);}#elsecgotoxy(4, MAX_EDIT_PREFS+3, GOTO_STAT);cprintf("FONT: %s",font_name);#endifint *dat = (int *)pref_data[cur_pos].ptr;#define WHITEIF(x) (dat == &x)?0xf0:LIGHTGREY_draw_hgauge(3, 1, 3, GOTO_MSG, msg_x-2, WHITEIF(msg_x));clear_to_end_of_line();_draw_vgauge(1, 1, 1, GOTO_MSG, msg_y, WHITEIF(msg_y));need_draw_stat = false;}int key = getch();struct prefs *p = &pref_data[cur_pos];int *dat = (int *)p->ptr;if (key == 0x1b || key == '\r')break;if (key == 'j' || key == CK_DOWN){cur_pos++;need_draw_stat = true;}if (key == 'k' || key == CK_UP){cur_pos--;need_draw_stat = true;}if (key == CK_LEFT)key = 'h';if (key == CK_RIGHT)key = 'l';cur_pos = (cur_pos + MAX_EDIT_PREFS) % MAX_EDIT_PREFS;switch(key){case 'l': inc = 1; break;case 'L': inc = 10; break;case 'h': inc = -1; break;case 'H': inc = -10; break;}int crt_x_old = crt_x;int crt_y_old = crt_y;int map_px_old = map_px;int msg_x_old = msg_x;int msg_y_old = msg_y;int dngn_x_old = dngn_x;int dngn_y_old = dngn_y;if (p->type == 'I' && inc != 0){if (dat == &dngn_x || dat == &dngn_y){if (inc == 1)inc++;else if (inc == -1)inc--;}int olddat = *dat;(*dat)+= inc;if (*dat > p->max)*dat = p->max;if (*dat < p->min)*dat = p->min;if (olddat == *dat)continue;need_resize = true;}if (need_resize){need_draw_stat = need_draw_msg = true;// crt screen layouts// Resize msg?if (msg_x != msg_x_old || msg_y != msg_y_old){upd_msg = true;region_msg->resize(msg_x, msg_y);}// Resize crt?if (crt_x != crt_x_old || crt_y != crt_y_old){upd_crt = true;region_crt->resize(crt_x, crt_y);}// Resize map?if (map_px != map_px_old){upd_map = true;region_map->resize( 0, 0, map_px, map_px);}// Resize dngn tile screen?if (dngn_x != dngn_x_old || dngn_y != dngn_y_old){clrscr();upd_dngn = true;tile_dngn_x = dngn_x;tile_dngn_y = dngn_y;region_tile->resize(dngn_x, dngn_y, 0, 0);}_do_layout();win_main->resize();win_main->clear();// Now screens are all black.if (upd_map)region_map->resize_backbuf();if (upd_dngn){region_tile -> resize_backbuf();tile_set_force_redraw_tiles(true);TileResizeScreen(dngn_x, dngn_y);}if (region_item)region_item->resize_backbuf();if (region_item2)region_item2->resize_backbuf();tile_set_force_redraw_inv(true);tile_draw_inv(REGION_INV1);region_map->force_redraw = true;viewwindow(true, true);region_tile->redraw();region_item->redraw();} // need resize} // while-loopclrscr();redraw_screen();mpr("Done.");}// Tiptext help infotypedef struct tip_info{int sx;int ex;int sy;int ey;const char *tiptext;const char *tipfilename;} tip_info;static int old_tip_idx = -1;static void _tip_grid(int gx, int gy, bool do_null = true, int minimap = 0){mesclr();const coord_def gc(gx,gy);terse_describe_square(gc);}int tile_cursor_x = -1;int tile_cursor_y = -1;int tile_cursor_flag = 0;void tile_place_cursor(int x, int y, bool display){if (tile_cursor_x != -1){// erase old cursorTileDrawCursor(tile_cursor_x, tile_cursor_y, tile_cursor_flag);}if (!display){tile_cursor_x = -1;return;}int new_flag = TILE_FLAG_CURSOR1;const coord_def vp(x+1, y+1);const coord_def gc = view2grid(vp);const coord_def ep = grid2show(gc);if (gc.x < 0 || gc.y < 0 || gc.x >= GXM || gc.y >= GYM){// off the dungeon...tile_cursor_x = -1;return;}else if (!crawl_view.in_grid_los(gc) || !env.show(ep)){new_flag = TILE_FLAG_CURSOR2;}tile_cursor_x = x;tile_cursor_y = y;tile_cursor_flag = TileDrawCursor(x, y, new_flag);}int convert_cursor_pos(int mx, int my, int *cx, int *cy){std::vector <RegionClass *>::iterator r;WinClass *w = win_main;int id = REGION_NONE;int x, y;int mx0 = 0;for (r = w->regions.begin();r != w->regions.end();r++){if (! (*r)->is_active())continue;if ( (*r)->mouse_pos(mx, my, cx, cy) ){id = (*r)->id;mx0 = (*r)->mx;break;}}x = *cx;y = *cy;/********************************************/if (id == REGION_TDNGN){x--;if (!in_viewport_bounds(x+1,y+1))return REGION_NONE;}if (id == REGION_MAP){x -= gmap_ox - region_map->marker_length + 1;y -= gmap_oy - region_map->marker_length + 1;}if (id == REGION_INV1 || id == REGION_INV2){x = x + y * mx0;y = 0;}if (id == REGION_DNGN){// Out of LOS rangeif (!in_viewport_bounds(x+1,y+1))return REGION_NONE;}*cx = x;*cy = y;return id;}// NOTE: Assumes the item is equipped in the first place!static bool _is_true_equipped_item(item_def item){// Weapons and staves are only truly equipped if wielded.if (item.link == you.equip[EQ_WEAPON])return (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES);// Cursed armour and rings are only truly equipped if *not* wielded.return (item.link != you.equip[EQ_WEAPON]);}// Returns whether there's any action you can take with an item in inventory// apart from dropping it.static bool _can_use_item(item_def item, bool equipped){// Vampires can drain corpses.if (item.base_type == OBJ_CORPSES){return (you.species == SP_VAMPIRE&& item.sub_type != CORPSE_SKELETON&& !food_is_rotten(item)&& mons_has_blood(item.plus));}if (equipped && item_cursed(item)){// Misc. items/rods can always be evoked, cursed or not.if (item.base_type == OBJ_MISCELLANY || item_is_rod(item))return (true);// You can't unwield/fire a wielded cursed weapon/staff// but cursed armour and rings can be unwielded without problems.return (!_is_true_equipped_item(item));
// Mummies can't do anything with food or potions.if (you.species == SP_MUMMY)return (item.base_type != OBJ_POTIONS && item.base_type != OBJ_FOOD);// In all other cases you can use the item in some way.return (true);
static int _handle_mouse_motion(int mouse_x, int mouse_y, bool init){int cx = -1;int cy = -1;int mode = 0;static int oldcx = -1;static int oldcy = -1;static int oldmode = -1;static int olditem = -1;if (init){oldcx = -1;oldcy = -1;oldmode = -1;old_tip_idx = -1;olditem = -1;return 0;}switch(mouse_mode){case MOUSE_MODE_NORMAL:case MOUSE_MODE_MORE:case MOUSE_MODE_MACRO:return 0;break;}if (mouse_x < 0){mode = 0;oldcx = oldcy = -10;}elsemode = convert_cursor_pos(mouse_x, mouse_y, &cx, &cy);if (oldcx == cx && oldcy == cy && oldmode == mode)return 0;// erase old cursorif (oldmode == REGION_DNGN && mode != oldmode){oldcx = -10;//_setcursortype(0);}if (olditem != -1){oldcx = -10;TileMoveInvCursor(-1);olditem = -1;}if ( oldmode == REGION_DNGN && mode != oldmode){oldcx = -10;tile_place_cursor(0, 0, false);}if (toggle_telescope && mode != REGION_MAP){TileDrawDungeon(NULL);toggle_telescope = false;}
bool valid_tip_region = (mode == REGION_MAP || mode == REGION_DNGN|| mode == REGION_INV1 || mode == REGION_INV2|| mode == REGION_MSG || mode == REGION_STAT);if (valid_tip_region && mode != oldmode)update_tip_text("");if (toggle_telescope && mode == REGION_MAP){oldmode = mode;oldcx = cx;oldcy = cy;_tip_grid(cx-1, cy-1, 1);TileDrawFarDungeon(cx-1, cy-1);return 0;}if (mode == REGION_INV1 || mode == REGION_INV2){oldcx = cx;oldcy = cy;oldmode = mode;int ix = TileInvIdx(cx);std::string desc;if (ix != -1){bool display_actions = (mode == REGION_INV1);if (itemlist_iflag[cx] & TILEI_FLAG_FLOOR){const item_def item = mitm[ix];if (itemlist_key[cx]){desc = itemlist_key[cx];desc += " - ";}desc += item.name(DESC_NOCAP_A);if (display_actions)desc += EOL "[L-Click] Pick up (g)";if (item.base_type == OBJ_CORPSES&& item.sub_type != CORPSE_SKELETON&& !food_is_rotten(item)){desc += EOL "[Shift-L-Click] ";if (can_bottle_blood_from_corpse( item.plus))desc += "Bottle blood";elsedesc += "Chop up";desc += " (c)";if (you.species == SP_VAMPIRE)desc += EOL "[Shift-R-Click] Drink blood (e)";}else if (item.base_type == OBJ_FOOD&& you.is_undead != US_UNDEAD&& you.species != SP_VAMPIRE){desc += EOL "[Shift-R-Click] Eat (e)";}}else // in inventory{const item_def item = you.inv[ix];desc = item.name(DESC_INVENTORY_EQUIP);if (display_actions){int type = item.base_type;const bool equipped = itemlist_iflag[cx] & TILEI_FLAG_EQUIP;bool wielded = (you.equip[EQ_WEAPON] == ix);desc += EOL;if (_can_use_item(you.inv[ix], equipped)){desc += "[L-Click] ";if (equipped){if (wielded&& type != OBJ_MISCELLANY&& !item_is_rod(item)){if (type == OBJ_JEWELLERY || type == OBJ_ARMOUR|| type == OBJ_WEAPONS || type == OBJ_STAVES){type = OBJ_WEAPONS + 18;}}elsetype += 18;}switch (type){// first equipable categoriescase OBJ_WEAPONS:case OBJ_STAVES:case OBJ_MISCELLANY:desc += "Wield (w)";if (is_throwable(item, player_size(PSIZE_BODY)))desc += EOL "[Ctrl-L-Click] Fire (f)";break;case OBJ_WEAPONS + 18:desc += "Unwield";if (is_throwable(item, player_size(PSIZE_BODY)))desc += EOL "[Ctrl-L-Click] Fire (f)";break;case OBJ_MISCELLANY + 18:if (item.sub_type >= MISC_DECK_OF_ESCAPE&& item.sub_type <= MISC_DECK_OF_DEFENCE){desc += "Draw a card (v)";desc += EOL "[Ctrl-L-Click] Unwield";break;}// else fall-throughcase OBJ_STAVES + 18: // rods - other staves handled abovedesc += "Evoke (v)";desc += EOL "[Ctrl-L-Click] Unwield";break;case OBJ_ARMOUR:desc += "Wear (W)";break;case OBJ_ARMOUR + 18:desc += "Take off (T)";break;case OBJ_JEWELLERY:desc += "Put on (P)";break;case OBJ_JEWELLERY + 18:desc += "Remove (R)";break;case OBJ_MISSILES:desc += "Fire (f)";if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";else if ( item.sub_type == MI_STONE&& player_knows_spell(SPELL_SANDBLAST)|| item.sub_type == MI_ARROW&& player_knows_spell(SPELL_STICKS_TO_SNAKES) ){// For Sandblast and Sticks to Snakes,// respectively.desc += EOL "[Ctrl-L-Click] Wield (w)";}break;case OBJ_WANDS:desc += "Zap (Z)";if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";break;case OBJ_BOOKS:if (item_type_known(item)&& item.sub_type != BOOK_MANUAL&& item.sub_type != BOOK_DESTRUCTION){desc += "Memorise (M)";if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";break;}// else fall-throughcase OBJ_SCROLLS:desc += "Read (r)";if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";break;case OBJ_POTIONS:desc += "Quaff (q)";// For Sublimation of Blood.if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";else if ( item_type_known(item)&& is_blood_potion(item)&& player_knows_spell(SPELL_SUBLIMATION_OF_BLOOD) ){desc += EOL "[Ctrl-L-Click] Wield (w)";}break;case OBJ_FOOD:desc += "Eat (e)";// For Sublimation of Blood.if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";else if (item.sub_type == FOOD_CHUNK&& player_knows_spell(SPELL_SUBLIMATION_OF_BLOOD)){desc += EOL "[Ctrl-L-Click] Wield (w)";}break;case OBJ_CORPSES:if (you.species == SP_VAMPIRE)desc += "Drink blood (e)";if (wielded){if (you.species == SP_VAMPIRE)desc += EOL;desc += "[Ctrl-L-Click] Unwield";}break;default:desc += "Use";}}// For Boneshards.// Special handling since skeletons have no primary action.if (item.base_type == OBJ_CORPSES&& item.sub_type == CORPSE_SKELETON){if (wielded)desc += EOL "[Ctrl-L-Click] Unwield";else if (player_knows_spell(SPELL_BONE_SHARDS))desc += EOL "[Ctrl-L-Click] Wield (w)";}desc += EOL "[R-Click] Info";// Has to be non-equipped or non-cursed to drop.if (!equipped || !_is_true_equipped_item(you.inv[ix])|| !item_cursed(you.inv[ix])){desc += EOL "[Shift-L-Click] Drop (d)";}}}update_tip_text(desc.c_str());itemlist_flag = mode;TileMoveInvCursor(cx);olditem = cx;}elseupdate_tip_text("");return 0;}if (mouse_mode == MOUSE_MODE_TARGET|| mouse_mode == MOUSE_MODE_TARGET_DIR){if (mode == REGION_DNGN || mode == REGION_TDNGN){oldcx = cx;oldcy = cy;oldmode = mode;_gui_set_mouse_view_pos(true, cx+1, cy+1);return CK_MOUSE_MOVE;}}_gui_set_mouse_view_pos(false, -1, -1);if (mode == REGION_TDNGN || mode == REGION_DNGN){if (mode == oldmode && oldcx == DCX && oldcy == DCY)update_tip_text("");oldcx = cx;oldcy = cy;oldmode = mode;if (mode == REGION_DNGN)tile_place_cursor(cx, cy, true);else if (mode == REGION_TDNGN)cgotoxy(cx+2, cy+1, GOTO_DNGN);const int gx = view2gridX(cx) + 1;const int gy = view2gridY(cy) + 1;_tip_grid(gx, gy);// mouse-over info on playerif (cx == DCX && cy == DCY){std::string desc = you.your_name;desc += " (";desc += get_species_abbrev(you.species);desc += get_class_abbrev(you.char_class);desc += ")";if (igrd[you.x_pos][you.y_pos] != NON_ITEM)desc += EOL "[L-Click] Pick up items (g)";if (grid_stair_direction( grd[gx][gy] ) != CMD_NO_CMD)desc += EOL "[Shift-L-Click] use stairs (</>)";// Character overview.desc += EOL "[R-Click] Overview (%)";// Religion.if (you.religion != GOD_NO_GOD)desc += EOL "[Shift-R-Click] Religion (^)";update_tip_text(desc.c_str());}return 0;}if (mode == REGION_MAP && mouse_mode == MOUSE_MODE_COMMAND){if (oldmode != REGION_MAP)update_tip_text("[L-Click] Travel / [R-Click] View");else_tip_grid(cx - 1, cy - 1, false, 1);oldmode = mode;oldcx = cx;oldcy = cy;return 0;}if (mode == REGION_MSG && mouse_mode == MOUSE_MODE_COMMAND){if (oldmode != REGION_MSG)update_tip_text("[L-Click] Browse message history");oldmode = mode;oldcx = cx;oldcy = cy;return 0;}if (mode == REGION_STAT && mouse_mode == MOUSE_MODE_COMMAND){if (oldmode != REGION_STAT)update_tip_text("[L-Click] Rest / Search for a while");oldmode = mode;oldcx = cx;oldcy = cy;return 0;}return 0;}static int _handle_mouse_button(int mx, int my, int button,bool shift, bool ctrl){int dir;const int dx[9] = {-1, 0, 1,-1, 0, 1,-1, 0, 1};const int dy[9] = { 1, 1, 1,0, 0, 0,-1,-1,-1};const int cmd_n[9] = {'b', 'j', 'n', 'h', '.', 'l', 'y', 'k', 'u'};const int cmd_s[9] = {'B', 'J', 'N', 'H', '5', 'L', 'Y', 'K', 'U'};const int cmd_c[9] = {CONTROL('B'), CONTROL('J'), CONTROL('N'), CONTROL('H'),'X', CONTROL('L'), CONTROL('Y'), CONTROL('K'), CONTROL('U'),};const int cmd_dir[9] = {'1','2','3','4','5','6','7','8','9'};int trig = CK_MOUSE_B1;switch (button){case 2: trig = CK_MOUSE_B2; break;case 3: trig = CK_MOUSE_B3; break;case 4: trig = CK_MOUSE_B4; break;case 5: trig = CK_MOUSE_B5; break;default: break;}if (shift)trig |= 512;if (ctrl)trig |= 1024;switch (mouse_mode){case MOUSE_MODE_NORMAL:return trig;case MOUSE_MODE_MORE:return '\r';}int cx,cy;int mode;static int oldcx = -1;static int oldcy = -1;static bool enable_wheel = true;static int old_button = 0;static int old_hp = 0;mode = convert_cursor_pos(mx, my, &cx, &cy);// Prevent accidental wheel slip and subsequent char death.if (mouse_mode == MOUSE_MODE_COMMAND && (button == 4 || button == 5)&& button == old_button && oldcx == cx && oldcy == cy){if (!enable_wheel)return 0;if (you.hp < old_hp){mpr("Wheel move aborted (rotate opposite to resume)");enable_wheel = false;return 0;}}old_hp = you.hp;enable_wheel = true;old_button = button;oldcx = cx;oldcy = cy;if (toggle_telescope){// Quit telescope mode.TileDrawDungeon(NULL);toggle_telescope = false;}if (mode == REGION_INV2){int ix = TileInvIdx(cx);int key = itemlist_key[cx];if (ix != -1 && key)return key;elsereturn 0;}// Clicked on item.if (mode == REGION_INV1){int ix = TileInvIdx(cx);if (ix != -1){if (button == 2){// Describe item.if (itemlist_iflag[cx] & TILEI_FLAG_FLOOR){if (shift){_gui_set_mouse_inv(ix, INV_EAT_FLOOR);return CK_MOUSE_B1ITEM;}else_gui_set_mouse_inv(-ix, INV_VIEW);}else_gui_set_mouse_inv(ix, INV_VIEW);TileMoveInvCursor(-1);return CK_MOUSE_B2ITEM;}else if (button == 1){// Floor itemif (itemlist_iflag[cx] & TILEI_FLAG_FLOOR){// Try to pick up one item.if (!shift)_gui_set_mouse_inv(ix, INV_PICKUP);else_gui_set_mouse_inv(ix, INV_USE_FLOOR);return CK_MOUSE_B1ITEM;}// Use item.if (shift)_gui_set_mouse_inv(ix, INV_DROP);else if (ctrl)_gui_set_mouse_inv(ix, INV_USE2);else_gui_set_mouse_inv(ix, INV_USE);return CK_MOUSE_B1ITEM;}}return trig;}if (mode == REGION_MSG && mouse_mode == MOUSE_MODE_COMMAND){return CONTROL('P');}if (mode == REGION_STAT && mouse_mode == MOUSE_MODE_COMMAND){return '5';}if ((mouse_mode == MOUSE_MODE_COMMAND || mouse_mode == MOUSE_MODE_MACRO)&& (mode == REGION_DNGN || mode == REGION_TDNGN)){if (button == 1 && cx == DCX && cy == DCY){// Pick up items.if (!shift)return 'g';// Else attempt to use stairs on square.const int gx = view2gridX(cx) + 1;const int gy = view2gridY(cy) + 1;switch (grid_stair_direction( grd[gx][gy] )){case CMD_GO_DOWNSTAIRS:return ('>');case CMD_GO_UPSTAIRS:return ('<');default:break;}}if (button == 2){// Describe yourself.if (cx == DCX && cy == DCY){if (!shift)return '%'; // Character overview.if (you.religion != GOD_NO_GOD)return '^'; // Religion screen.}// triggerif (mouse_mode == MOUSE_MODE_MACRO)return trig;// R-Click: try to describe grid; otherwise return trigger key.if (!in_los_bounds(cx+1,cy+1))return CK_MOUSE_B2;const int gx = view2gridX(cx) + 1;const int gy = view2gridY(cy) + 1;full_describe_square(coord_def(gx,gy));return CK_MOUSE_DONE;}// button = 1 or 4, 5// First check if 3x3 grid around @ is clicked.// If so, return equivalent numpad key.int adir = -1;for (dir = 0; dir < 9; dir++){if (DCX + dx[dir] == cx && DCY + dy[dir] == cy){adir = dir;break;}}if (adir != -1){if (shift)return cmd_s[adir];else if (ctrl)return cmd_c[adir];elsereturn cmd_n[dir];}if (button != 1)return trig;// Otherwise travel to that grid.const coord_def gc = view2grid(coord_def(cx+1, cy+1));if (!map_bounds(gc))return 0;// Activate travel.start_travel(gc.x, gc.y);return CK_MOUSE_DONE;}if (mouse_mode == MOUSE_MODE_COMMAND && mode == REGION_MAP){// Begin telescope mode.if (button == 2){toggle_telescope = true;StoreDungeonView(NULL);TileDrawFarDungeon(cx-1,cy-1);return 0;}if (button != 1)return trig;// L-click: try to travel to the grid.const coord_def gc(cx-1, cy-1);if (!map_bounds(gc))return 0;// Activate travel.start_travel(gc.x, gc.y);return CK_MOUSE_DONE;}// target selectionif ((mouse_mode == MOUSE_MODE_TARGET || mouse_mode == MOUSE_MODE_TARGET_DIR)&& button == 1 && (mode == REGION_DNGN || mode == REGION_TDNGN)){_gui_set_mouse_view_pos(true, cx+1, cy+1);return CK_MOUSE_CLICK;}_gui_set_mouse_view_pos(false, 0, 0);if (mouse_mode == MOUSE_MODE_TARGET_DIR && button == 1&& (mode == REGION_DNGN || mode == REGION_TDNGN)){if (cx < DCX-1 || cy < DCY-1 || cx > DCX+1 || cy > DCY+1)return 0;for (dir = 0; dir < 9; dir++)if (DCX + dx[dir] == cx && DCY + dy[dir] == cy)return cmd_dir[dir];return 0;}return trig;}static int _handle_mouse_unbutton(int mx, int my, int button){if (toggle_telescope)TileDrawDungeon(NULL);toggle_telescope = false;return 0;}int getch_ck(){int etype = 0;int x1,y1,x2,y2;int key;bool sh, ct;int k;while (true){k = 0;GetNextEvent(&etype, &key, &sh, &ct, &x1, &y1, &x2, &y2);switch(etype){case EV_BUTTON:k = _handle_mouse_button(x1, y1, key, sh, ct);break;case EV_MOVE:k = _handle_mouse_motion(x1, y1, false);break;case EV_UNBUTTON:k = _handle_mouse_unbutton(x1, y1, key);break;case EV_KEYIN:k = key;break;default:break;}if (k != 0)break;}return k;}int getch(){static int ck_tr[] ={'k', 'j', 'h', 'l', '.', 'y', 'b', '.', 'u', 'n','K', 'J', 'H', 'L', '5', 'Y', 'B', '5', 'U', 'N',11, 10, 8, 12, '0', 25, 2, 'C', 21, 14};int keyin = getch_ck();if (keyin >= CK_UP && keyin <= CK_CTRL_PGDN)return ck_tr[ keyin - CK_UP ];if (keyin == CK_DELETE)return '.';return keyin;}
}void mouse_set_mode(int mode){mouse_mode = mode;// Init cursor etc._handle_mouse_motion(0, 0, true);}int mouse_get_mode(){return mouse_mode;
if (region_tip)region_tip->resize(geom.hudsz.x, 3);region_msg->resize(geom.msgsz.x, geom.msgsz.y);region_stat->resize(geom.hudsz.x, geom.hudsz.y);_do_layout();_init_regions();}void lock_region(int r){if (r >= 0 && r < NUM_REGIONS)region_lock[r] = true;}void unlock_region(int r){if (r >= 0 && r < NUM_REGIONS)region_lock[r] = false;}/** Wrapper*/void clrscr(){win_main->clear();TextRegionClass::cursor_region = NULL;// Clear Text regions.if (!region_lock[REGION_CRT])region_crt->clear();if (region_msg && !region_lock[REGION_MSG])region_msg->clear();if (region_stat && !region_lock[REGION_STAT])region_stat->clear();if (region_dngn && !region_lock[REGION_TDNGN])region_dngn->clear();if (region_tip && !region_lock[REGION_TIP])region_tip->clear();// Hack: Do not erase the backbuffer; instead just hide it.if (region_map){if (region_lock[REGION_MAP])region_map->redraw();elseregion_map->flag = false;}if (region_item){if (region_lock[REGION_INV1])region_item->redraw();elseregion_item->flag = false;}if (region_item2){
if (region_lock[REGION_INV2])region_item2->redraw();else{TileClearInv(REGION_INV2);region_item2->flag = false;}}cgotoxy(1, 1);
geom.viewsz.x = 17;geom.viewsz.y = 17;
TextRegionClass::textbackground(bg);}void cgotoxy(int x, int y, int region){if (region == GOTO_LAST){// nothing}else if (region == GOTO_CRT)TextRegionClass::text_mode = region_crt;else if (region == GOTO_MSG)TextRegionClass::text_mode = region_msg;else if (region == GOTO_STAT)TextRegionClass::text_mode = region_stat;TextRegionClass::text_mode->flag = true;TextRegionClass::cgotoxy(x, y);}void _setcursortype(int curstype){TextRegionClass::_setcursortype(curstype);}void enable_smart_cursor(bool cursor){gui_smart_cursor = cursor;
TextRegion::textbackground(bg);
int xx, yy;unsigned char *ptr = buf;//cgotoxy(1, 1, GOTO_CRT);for (yy = sy-1; yy <= ey-1; yy++){unsigned char *c = &(r->cbuf[yy*(r->mx)+sx-1]);unsigned char *a = &(r->abuf[yy*(r->mx)+sx-1]);for (xx = sx-1; xx <= ex-1; xx++){*c = *ptr;
void clear_message_window(){tiles.clear_message_window();}
ptr++;if (mono)*a = WHITE;else{*a = *ptr;ptr++;}c++;a++;}}r->make_active();r->redraw(sx-1, sy-1, ex-1, ey-1);
void update_screen(){tiles.redraw();
FILE *fp = fopen(name, "r");int max = get_number_of_lines();
// Look for the presence of any keyboard events in the queue.SDL_Event store;int count = SDL_PeepEvents(&store, 1, SDL_PEEKEVENT,SDL_EVENTMASK(SDL_KEYDOWN));// SDL Error?ASSERT(count != -1);
#define DELIMITER_END "-------------------------------------------------------------------------------"#define DELIMITER_MORE "...(more)... "unsigned char buf[80*MAXTEXTLINES], buf2[84];int nlines = 0;int cline = 0;int i;
#ifdef UNIXint itoa(int value, char *strptr, int radix){unsigned int bitmask = 32768;int ctr = 0;int startflag = 0;
for (i = 0; i < 80*MAXTEXTLINES; i++)buf[i] = ' ';while (nlines < MAXTEXTLINES)
else if (radix == 2) /* int to "binary string" */
i = 0;while (i < 79 && buf2[i] != 13 && buf2[i] != 10)i++;
if (!startflag) /* Special case if value == 0 */sprintf((strptr + ctr++), "0");
fclose(fp);clrscr();while (true){cgotoxy(1, 1);if (cline == 0)cprintf(DELIMITER_END);elsecprintf(DELIMITER_MORE);
return (0); /* Me? Fail? Nah. */}
cgotoxy(1, max);if (cline + max-2 >= nlines)cprintf(DELIMITER_END);elsecprintf(DELIMITER_MORE);
// Convert string to lowercase.char *strlwr(char *str){unsigned int i;
cgotoxy(14, max);cprintf("[j/k/+/-/SPACE/b: scroll q/ESC/RETURN: exit]");mouse_set_mode(MOUSE_MODE_MORE);int key = getch();mouse_set_mode(MOUSE_MODE_NORMAL);if (key == 'q' || key == ESCAPE || key =='\r')break;else if (key == '-' || key == 'b')cline -= max-2;else if (key == 'k')cline --;else if (key == '+' || key == ' ')cline += max-2;else if (key == 'j')cline++;else if (key == CK_MOUSE_B4)cline--;else if (key == CK_MOUSE_B5)cline++;
for (i = 0; i < strlen(str); i++)str[i] = tolower(str[i]);
#endif // #ifdef UNIX
/* ************************************************************************ called from: acr* *********************************************************************** */void tile_use_item(int idx, InvAction act);
void tile_item_use_floor(int idx);void tile_item_pickup(int idx);void tile_item_drop(int idx);void tile_item_eat_floor(int idx);void tile_item_use(int idx);void tile_item_use_secondary(int idx);
else if (act == INV_DROP)
}void tile_item_pickup(int idx){pickup_single_item(idx, mitm[idx].quantity);}void tile_item_drop(int idx){drop_item(idx, you.inv[idx].quantity);}void tile_item_eat_floor(int idx){if (mitm[idx].base_type == OBJ_CORPSES&& you.species == SP_VAMPIRE|| mitm[idx].base_type == OBJ_FOOD&& you.is_undead != US_UNDEAD && you.species != SP_VAMPIRE)
if (mitm[idx].base_type == OBJ_CORPSES&& mitm[idx].sub_type != CORPSE_SKELETON&& !food_is_rotten(mitm[idx])){butchery(idx);}return;
if (check_warning_inscriptions(item, OPER_FIRE))fire_thing(idx); // fire weapons
if (mitm[idx].base_type == OBJ_CORPSES&& you.species == SP_VAMPIRE|| mitm[idx].base_type == OBJ_FOOD&& you.is_undead != US_UNDEAD && you.species != SP_VAMPIRE)
if (you.equip[EQ_WEAPON] == idx&& check_warning_inscriptions(item, OPER_WIELD))
const item_def item = you.inv[idx];
wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield}else if (_valid_weapon_swap(item)&& check_warning_inscriptions(item, OPER_WIELD)){// secondary wield for several spells and suchwield_weapon(true, idx); // wield}}
if (item.base_type == OBJ_WEAPONS&& is_throwable(item, player_size(PSIZE_BODY))){if (check_warning_inscriptions(item, OPER_FIRE))fire_thing(idx); // fire weapons}else if (item.base_type == OBJ_MISCELLANY|| item.base_type == OBJ_STAVES&& item_is_rod(item)) // unwield rods/misc. items{if (you.equip[EQ_WEAPON] == idx&& check_warning_inscriptions(item, OPER_WIELD)){wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield}}else if (you.equip[EQ_WEAPON] == idx&& check_warning_inscriptions(item, OPER_WIELD)){wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield}else if (_valid_weapon_swap(item)&& check_warning_inscriptions(item, OPER_WIELD)){// secondary wield for several spells and suchwield_weapon(true, idx); // wield}
void tile_item_use(int idx){const item_def item = you.inv[idx];
int draw_quantity = ie->quantity > 1 ? ie->quantity : -1;bool is_item_on_floor = true;bool is_item_tried = false;char c = 0;int idx = -1;if (ie->item){is_item_on_floor = ie->item->x != -1;is_item_tried = item_type_tried(*ie->item);c = ie->hotkeys.size() > 0 ? ie->hotkeys[0] : 0;idx = (is_item_on_floor ? ie->item->index() :letter_to_index(c));}TileDrawOneItem(REGION_INV2, get_entry_index(ie), c,idx, tileidx_item(*ie->item), draw_quantity,is_item_on_floor, ie->selected(), ie->is_item_equipped(),is_item_tried, ie->is_item_cursed());
char key = ie->hotkeys.size() > 0 ? ie->hotkeys[0] : 0;tiles.update_menu_inventory(get_entry_index(ie), *ie->item, ie->selected(), key);
enum map_feature{MF_UNSEEN,MF_FLOOR,MF_WALL,MF_MAP_FLOOR,MF_MAP_WALL,MF_DOOR,MF_ITEM,MF_MONS_HOSTILE,MF_MONS_FRIENDLY,MF_MONS_NEUTRAL,MF_MONS_NO_EXP,MF_STAIR_UP,MF_STAIR_DOWN,MF_STAIR_BRANCH,MF_FEATURE,MF_WATER,MF_LAVA,MF_TRAP,MF_EXCL_ROOT,MF_EXCL,MF_PLAYER,MF_MAX,MF_SKIP};
#ifdef USE_TILEif (key_command == CMD_TARGET_MOUSE_MOVE){continue;}else if (key_command == CMD_TARGET_MOUSE_SELECT){const coord_def &gc = tiles.get_cursor();if (gc == Region::NO_CURSOR)continue;coord_def delta = gc - you.pos();if (delta.x < -1 || delta.x > 1|| delta.y < -1 || delta.y > 1){// This shouldn't happen.continue;}moves.dx = delta.x;moves.dy = delta.y;moves.isMe = (delta.x == 0) && (delta.y == 0);break;}#endif
#ifdef WIN32TILESint old_main( int argc, char *argv[] )#elseint main( int argc, char *argv[] )
#ifdef USE_TILE#include <SDL_main.h>
case CMD_EDIT_PREFS:edit_prefs();break;case CMD_USE_ITEM:{int idx;InvAction act;gui_get_mouse_inv(idx, act);tile_use_item(idx, act);}break;case CMD_VIEW_ITEM:{int idx;InvAction act;gui_get_mouse_inv(idx, act);if (idx < 0) // item on floordescribe_item(mitm[-idx]);else // item in inventorydescribe_item(you.inv[idx], true);redraw_screen();}break;
#ifdef USE_TILEtile_draw_inv(REGION_INV1);#ifdef USE_X11update_screen();#endifmouse_set_mode(MOUSE_MODE_COMMAND);
mouse_control mc(MOUSE_MODE_COMMAND);