New: colour.cc, coord.cc, coordit.cc, random.cc, rng.cc.
LUSG5HYFRMFNS3RACRCUJNQXJNXPL4SYKHHOIEG5RBQG2DKQXPDAC 7FIX6VVO7QUIPJVX7K5LOSD7MON3KY6GJH3USKOT566ZWACVJMZAC DXBPUEUNPDXUWFR5ZK5LYFDZJFNKGNCPOGEQNO6TTFSBHOFH6H6QC EIWZGID56VJJUOTCZH3OBLXMS7GWCBFOKRL2QIZ2JRLXPEEBAUIAC QPM2SLQPKICB7SP6PIPEWPD2SMFF3NUSDLMCWSWWSJJWQCPBKWOAC PQYSVXOLM6L4OGWQNXUHXXNUXJ33TTS36TIVHRPKMYQHQY42EBNQC DKYR3HEORWRCTEUA525ZBPUAWS5B6VFV5CCIGGVDH5NG6YA4D3ZAC SDGK6QEAHVCMRJVWSHZUECXXC5ZSJ2PQYTZWN3KX5UQFGAWI4Q3AC P5HXZFSDGCYC5L7FY7VATY74WFLGYL4WAERPGTO2P64EURULMV4QC CLO5METZJ4WBV3KWGW3WJ4WY5NYWCOHCGEIMJU4NYWKECWQ536QAC QAD5QRQDRHBP2SKJXPYAHIJOUUBXQTJEAMJUU274I3UY2WW7FEXQC XHKAHAVDZIGGXNA442YKWKCTSSIRFTXOIOFYLYEJAR36H7DLD2ZQC NT5SNG44MU2JRBQA55TR27YDMA6SMKAP2ANDCROS3T2IL7ATLFUAC KHIL64HDOAMK3KGECPUPQFUOZ76G2J7M5BSQR2YUBYCHB4DZ6V3QC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC SQKPN77WI7ZTJPVBVGLFGVH6OPDMOKLI6A4PEW6ULHFETJLFJNGAC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC BR6HF3PWCXUG24OBIWTCZ64DDVBA2G6BQBDJ5V5WMARRQBG2CLGQC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC NLQNXH3SVJ52CWXEV35FSSZP32VHC4QFGN3HINF4KO5GZHZMOBKQC HQTS3VQ6PNUZKHNVEWMML7JNAAAKL4DSW3KFSRCCSLGYTDHZFCCAC 7NDXS36TE7QVXTXJWMYSVG5UHCCLPIO4VL6NXFGTDK3ZNKE3A2IAC 77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC IAAPG4VMQN6O4CZYNR5QA7MXWVII5USVV2HRX2MDAF2GLDGRUZGAC TFZ4TER7O2Z4FOGF2RCPEPYIHBTUA4LG3ECXLR7XGLCC6GO6OOTAC BBQWA33DPXWEDYOOPO45VAYD4JQDZQVMZSEJ4RUI5LLC733IMIIQC Q3B3UVMYEVC4YJUPYVSNTR4DJH4E6J4JJDHZNT5LNOCHCPPMEMXAC F7X6HVUKHZXYURABYAZJHRYBV7UZTIPOWJMGCMDK26FQ66WGKFZAC QEEJFAETO6B2J4IWDIDCJ5UNIFNNHHG22IWF2CUJRTJJBNE47CWQC 25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC OYTCBRC7LE44EUVRZVYTOOVKQWJ6P6YE3FXTOGUTNKEMLNWPHKSQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC 6BYKOHEMLXXUKTH56UHJ6YQ6VWQCBWSSTCXFDT33RNID4G4ZUIKQC FIYBXLWALQINNQTHG2KNDUUTAQAZRDDLXW2XOVSKDKBADJ3XCJ4AC OVYFNBS6TZ7DGYA3TYM7N244T4M6JE6ISAPOZKOMRRAQEEIVPXBQC UADYVV3UD5ERJTZZJGY4EUQ4NJ2JSBG7YYUJ75ZRBIXRQXQKOJPAC GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC 22YVHM74WBJNJE4PA5CBEUTDWM6FAGGGILI26A4LXAURX55TNRKAC QS3ZRS3E6KL3YJHPKYEWCWJYRBJSXD5OOYF6Y25HZVECGPJRDB5QC 5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC JK3HFJG76OOQHJMXJUSZRTR5CX5ZMS52LRVBLOR7E2NBI6PRSHHAC KZWOHH536QBWAPWROR32EOXEK5LRY6I5VHVL7HHI7GOFKCMQTCSQC 5XNQ3SSNBFXFNWA6DPM74W6FH65NX665P3DMH6YCWVFOPZTJSYCQC VJDLV4PF2ZJ46NERO4LZUX5JE2CD5XBOBQCYYPTFWTHLUEYDUOYAC GF5VGZLKKWIATLVLTUJR4LVEQZAKR7CWMLNFMJXA67WLHP7JNUUAC MV5USMLTBKVRWBAD67UFJ2BS4Y5HEOMYASRSB44DS24BBMRP75RQC RIW55YSFKKTJLBTOJRVUBC7JOFUBOK7OBMISW4PBSVLYJHAAKPPQC AXRXY7RSEN3QHQRK6SFEH2OZAAYJRR5RBBBFF4YJF756V2FPFJ3AC LUH6GAJODIQXNPBEHMSUTKH3KA3DYVRCKZ6GJJ4HHNHOIMMUEP6QC VQZEJTCSRZ5RVLCCKUCIS3IVZPFYRC26I74X4WIJAPEY7NYID2UQC YTIPWYSKK63WIUKVYLCD2WQUYIBW4R57653MOCJWIKNIFCNHA2DQC TADKPTKH3CWXZRGVDWOY3CMAQ6CQISITDYB4F27YU53U5XEB6NVAC GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC OMAUFQNBWGX4FDABHQCVPGDYRVKMDASGQJVRH7AOPPEMHAP2LQSQC B7DNCNY7SXL5WAW5B3XZP5KIQSBWOJ3N2YW46WOUQKTRBRRZ7YOQC YKVVFNKT2M5WG2KBURRTOJG23BJVI6WUBP5JOGYPHQBS4RNGFGWQC TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC KZNUAHJQUBM6MEVUSSWG734AXZ3NZYMRJ2XFQLRGXJ3MSTBV7ELQC 4OKEEU32EGHIDAJ75GH3USSQHQPZBDZVC7TOP7ALMHZRUFPE5WEQC X7TRUBJTRDVUI53BROBYHF4UDC4I5SUYWBUOGQMZNN2WEZAFVGVQC WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC UKN6HTZXDUUOWKNWNKWPHKGUGL474JIAQN5JU3DM3DU26WGMNP4AC CCRQESB4ADT4WA7FGLNZZXAJ6G5QMCTYCZIWORBN45P6ZPILC34AC SOCJXX6MMOXLBEWBID4QN5FW2YNYULNNN7K3IRL7RSWK5EUNAZLQC BAQ5ZQ3XMXTITZIDAGMES65SE6Y7VQYASNMTYPL3OOJEG4YMGVPAC L6YPJVODN32IYLEZQQZE2ENH3XDAZ63IQIDX3PB4CJEK3A4NUNSAC Y56C5OMUQ5XF2G6DKDV4R5MED44UOIUPTBBQVWQBUHYIXYA5MOZAC 7JMN4TTOB7J56UAHT47USGLXARDHDEB7SYIHA5QTGMDX3AZ6ZCSQC J7GPW2YXLT6FGSKJ24FGQ24GTRZ6A2BDYM6CIXV4R6YBEHP6BGPAC MPMVK6J5UQUFJ75SNRSPIBBSRTH67ZPDZKPZUF3RZRFKSERS62AAC IHV7JHD4E67NEGLZEO3FPQGJPJF3IAV6QV5A63FPG4SU2VRFV47QC BMXIXQKM2247TENYZSOULFAT6VSZJNGGFBQ3SN7IOM4ROQRVTHZAC HBABF6EDHS4K7QKQU6NM3L3FDIZN3N345MN4KFGHY7XGTX34TPIQC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC 5KTPCJG42MF2B34CEH6VXAJIOZR6QOS2BWYNW7DXM3WA7N3GH4HQC SFWCESFCUEVKJ6ZQQX3Y5YTIQD5BC6MCVSLVZFRGRTU46BFLKKWAC S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC TQXNC2YQVJZXBPSLDEANMM2EDGHTH4DSN74OJIRMUF7D46SESHZAC UIVESOFZ4C262RYTFHSTFZIYTPTWSRJCFJAOZX7O2PQ35DFRDDEAC JZ4YC57SR2WQJIEIZSO3ZECA2FNMQUB7JYFKID4SIQ3RQ5NYXIVAC C7MS2OSFVKCD7M7H5WKFAX3WXAWK4O3JULA56WPSXFXE22XB4QSQC 4C6O4H7IO3LDZPBDGRST3QUFKMNQRB4Y6JXUV3NKIJVVPLAA2AWQC 4J2ILW7DGFLSRYX2TF4OYWN3WNJSQXC647MQGGIOBC63MPF4TXKAC UANJI74DZW4MVGWK53MAZ667HAARWAURFOHKFBPSW4OFZ4C6LPCQC XKL3ATYU6YNHKOGQCVJVQR7YG2I6KPYGWUNICZ7NSDKLNM4UGK3AC YTRHJZ4YBCNEI4UY4AGEIVKY66C7IJZ7ESFLXTULTSWV4KF5DG3QC VS246W2SVNBUAI5SZE3RS5WPQWLEYXHHJHFXP45BZO76CB56NI6QC 4HATGRJJE7Q6LXHJ3ZGYTNBLG542KAUEK6ERKARIYRKRWY6VTDKQC 5T2S4AV7WKL22RUZBMQMOSDQ5JRXPA74SMNQEZWXYMLPI7PB7R7QC YVQMLXJPDEBW7VXLTVXRUHSR66233VUWCXIYLUTERUBBMBMPSIIQC 4VK7VHWRVRO66BRSGTBPSYJGGXLRF6AG6G74UDTPHTPXR7ZRNINQC ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC FG6S2SNKFZWJK7PYHASHXU32ORYBOLGFL5RWQVDJ47MFVS4VMQHQC IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC RWH6IAVXQD3Q7ITNN5WOOUHBDBYURLXFEURA7QFHS4ZED2CG7MOQC OE3TD4J5FSIFAM37J2UPEV7QQNXLSZM6GDUMPI66LC5LW2OM2J4AC 6ZZO2QBB46RZM6OXVS7OIKC5M3SEAULSSJFXW5PJG556JDKKUHWAC 5FHWTG7M6FW4B3I33YI7QSM3OZIB6ZGC6TI6JISSLY5Y43HI56VAC 3ZNI2YMHYXRVEONY5CGWXSRMFSLOATZMKU7H6HRY3CC2W6OZAM7QC IPPPBA4G2LODBP3EJIYGUAAOMHKLNBXHBD7KVX2JVDTA4DETHO4AC VDWXI5MMXZLJXWWPZPXJZ2YZIR2OMPQO3VIJO2HMTF4TPYJB2MDQC YFIVTYI7PMVAXV23DUPXPAQNEY3YSFIXQGSN32I3WVHMMD5XS5DQC SNH6UWOYVWP4A6B4NC6YZ6KRYPYCGGNYCW5TILTALPH552H2EUFQC POP6UTTHSJGDU5NU7ENQJOZVFUHYM63HJ6HLPXDDLK7XFIP4XEIQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC ENI6P5WUO7DS4Y7EUDCYB4PSNT7CXH2L5JIB5BLZHNMWN4QDXMWQC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC Q43X3MHS6IVLGSIIUJMTZT6NO6S4BDAUAJE4UJBXN4KWRFPLYZEAC P2YNOE2TUTZFAOBTHJOIVD6TCV7J7D2UKUX67LHZUL6QY44ZMENQC PO3IATZV4JX3I3522UAGF53ZLZ4FW7C2J32Z23PEWQVHGGEUO7SAC KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC 475LL4U4ND6PTNV4XKC7WQAOJC7RF2VCCVX3DRILP2PKIBFYWE6QC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC RCYCFKHI7HUB46VKURMSKGGV2PCMXOCAJQMYHI5AJNGZEEKMIPFQC ZEFGFQHN6J2S6EIPX7EPDG22C5YXTI6DMKQHHRCLWN5MQC44KY3AC 2TFYJ7D72JY4DYQW3GSPEONA2WYIVHAJXTIQ2QRDIWF65XN2QFGAC QBAHRGJ2RVSMWKXY2B4FVR5VX75GILH6HSRYGF44PBPNINST2NIAC U3UHWTM2LW64BR5DEBMMZUIGXGS2H3IYSGTWYI5ZU6LD4WWYKRPQC G7CTMQ3VNTAB73ZI3LNZHKTAJ5LEQEGG772MVFQQ5XXLCMJVORTQC S7KC3IFKCUNBO3XO4TV3KEQEIDZWSRJSKXY65DPONKMG54VHU3UQC BIZDHHK5LIO57S5AKHEPJFLWV5DAFKZIKYBGOUNGICSWTX7DCXKAC 5UC5TI7B6NWGIGN74QRBZKDBYUMHLM2ZO5ATXEZ6TZOGOLF3JX5QC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC NMRKYZUPI6EOC4KONJKB2RHSCC6ONYJUOXQJ7PYJ7V4OBWPRO7AQC 6EJRFPJJRSIISDNDZWODH5A7U4PVIWH4YUCHEPB4V2GLGFG4DLBAC QFIV4YISNBTC5QXN7JYHEL3FBFWIQ2HKJ4YBDCZYTQ3PMPFE653AC WNQLH6VJ5DIPNQJUSUQBEKGNOZYCVWU5BYP4W6WQZBRMSR7GLUUQC VEHHZZFWDG5M4IXTCXXMKH3S2FSXTZ4CD23J6AYVFEPY7PBZ7GWQC YQ5IYBHW2ICYKOC2M6CI5BNOZKST3DIMMZRQN72LUQCHDAPVYQCQC KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC LE5U6CTXEIETQN5GOVYF2K2VCISRXR3ULORXDKIKWYDVBG5GS3WAC KXUQB3WNWC5IFL6VFWADEPQMMU3VV3NDI5FLA666PGOEWFYUHCLQC JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC DCZMEKDHQWSQCQYQD6ZXB3XOMWLVLPSPVSBVVMPXMSZF7GO3BVCAC DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC C25ULNTKMNOXT72ERWSFQZQW5E2OIM3TOGAAA33Z7EZQMZHRS2MAC COLMJH3UIQFF4R5AV642OJK4HHGUIIPLNP5WGKLWWYNJV7ZGPI7AC ACZYEIX7WMPIIODKCATBCUE626AJ4ZGGBOMVC6BGXM27EQU2RECAC RGO2JV5HFKZFXO7KJWDXGDMNBR6NIAOMJW34NHRTLLVN2N7XGW7QC WNC5SY6P2PBCU62Q2DB5J2M4HPDS5EJY76ZEPHRGGCLJ4BSLBSSQC LPTP6ZL7U4OVXLZ56TJKJ6HENDHE7ITFMFBXC5BKEBVXEGXPW44AC 3A5FX3Y4RPKWQEHKKXZKXZJ7RKV6RKWT7GTR4WFE5UBWKV2HT4RQC T7CCGLOZ25B7BQKKGR6IA6LWBRKUWTXLTIRXUQ4YKQRVAA7AHZKQC XP6MR3Q24DQOWNEGMSHJX54ZAISKOIF65IR65M4EOR45KR2OSFVQC RXYHE3C7R3EGCRZEJT2ZO4ALLRDR3HF66VHZZNF7TT3DFWZ6BJCQC XPIE6FG6SYZXNQFBRWUBJ3NR5Q6MOMRXAFW3WTKMSLMKKA55ZWCQC IGUSSYANPKGMX5YDQC7AI5ZWZLEQPIXA4KG3RZHNPMERL554HQWQC 754PQVFHYQER7P7NEHYNLQVOEALF6I23IQDNGNCOK5IV7OLAEXRQC RJIGO3YE7LKSLASPVA7K6CNWJAPKXD7ENJDURI5GXBGIEXFBBINAC ZLQAAP55CJ77XIJN3DZVPT4GTTVLIBFJLIJJKI6L5UBSHX7VUK6AC AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC UBQTNLYGD3SNWMUNGWUPX7EXEGQXOXCFCPWIVWBFE7ID7DJLPFWAC CJKLBIIM2ZTWTLGISXEZOGK2JANEYUSLOKG3BBOAYAY7AFG33ELQC JTVUAALTZP6FW3D3QJUSOUGMEDNZB4F4HGUMYFHWGEJV2ETRBIBQC D6A2MLKI7UQPZ4A4D6QSM6STFVDY77IY5APXCBT3LNH6CDVKT67QC U6OTXM3JN7SGPVIGQ5F6NR2I7J5V7KOWFQ7AVNNRQQDNLBEDMYFQC 2ESKXYN266CEMLSL6DNCKG4REDO34FXL4ODVGMWDJTNJRKMXWCRQC VM7ZJXYXF3XTGYLWW5RXTEFGG46FOOWWEATC6S565BGHBGM3CXUAC HSRRNAU5UAYC6B6IQWGJPFROMZBTJICPCH6DJVZDHDTAGOQ6IOYAC SBJWTFK2LCN7IIFREIZWTWV3U3LSZA2IPEOVXTN2ZZYHVEOHWBWQC YATODO2EN3AW7IXW5PL25HHK34YHF6Y32QBMOUZXEATZZ4YQQWZQC TPO6FNMPNUSWH4NCKO3VLYNAADEPSAXLUITCCACLZZSY53PKA62QC 43ZTEB57FU7KE5EVMYWZONNVJBZCGF3JEAJZIY25LC4LGE65PG5QC DGB7DKTR6OEQEMOOF3MAHDT4PAPKZ54Y33MWYVD7XIOESPFAXHQQC IXWJ54CASZWYHSTDOU3TRQS2DSF4MKBRPO4VZYLE72JL5RD22O2AC O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC ASLW3Z5PAVZSWJEMMMVZT226P44EKSAD47QS72JIFJESAI3RPN3AC OFH2B2UZBK43QLFQBZ54FOCFLFNE54BZVDNCEUGDTBCUGNVZULIQC K2MLPJIAXXZRWEWZCNSGICCBNIU2WAAPT7SPIMOH7FLLTOB4QFRAC O3QBT2ISABMEWTNSYEJKAJG6LZMON7U6RQZDSLY2KQHSMILUYQFQC AMSENYIGRJWHHGHLKIZQGZZQTWCZBTS2Y3WKPVTZZRI7ZMTATBCAC 57E4T664CXRFPVW2BZBYI33UIHFS4PSEZURZYPSYSZK5DRLJJ5CQC QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC HBHQQDULNVWISJ75XIL6R6BFEDYRNY22NX3ZTFVNP5ZWJGJSKOEQC OXHOOJE4XEQKGI3JKURNSITG6CRQFAOFQ2EKKG6M5DCLN7LS4GUAC OYYZVCE3QHBVJM6IEKK5HTJRG5YOVQNCBRMSJENTHOI2WPJLNCFAC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC FFERAWJ5ZXJW3N63T4PENDNVV7HOJ6IUH7QD2RXX7723MKZSP4BQC XJRP5MAESWFGYS4CBM7K2ENA3UBPL6N6MDNAHJBH2WRMZ73E5JGQC 4XGOVPFCU6KZIYHKWCHUTZY6G5S326DKBG3UREPR34Q4TSDD3TAAC GVCGKTH5IJ4VSQEIN4CRC7ZFVZW26JPIYNCPTO7GY66CSZZEW3ZQC HIRKGUMNJPWKSVTR6TVBPD3MWNA63CEHCLCIPWEMGDFHVB3NPLDQC OONYLF4DAPLIYLBNNRW74IVT5BBTWI4XHQBXSNSPVRX3FTKJBTRAC GQQ6ASWTYODIHG7X32JNUUHP5NMOVZJIHWGS3F3MKRYZGAHP6NVQC ATDAT2AONG2BDLZFBJZB4WVNRUFQAU7RDIVUBAZ6STAV62NX5R4AC LW4N5EHKL776DURXZMAM6JEW3JPWWX5BSNP7TCZHTLCDOQTTGFCAC DKRSOHZXL6EPSLKOKHF7GJXSZEJVY7CXGACSHWLM5B5FTRETWWCAC 2P3IJKK547AOEFWKXEAL73QFKW423GGAZEZHW6OZ6QB7YUSDNC3AC KR655YT3I3U5DMN5NS3FPUGMDNT4BI56K3SFF2FNJ77C45NFKL5AC ZHH4MGCGXMAKIZ4GVA6Q4MS3IWJTGNMWLPSAG2MWLQS2G3WU5YCAC ZIFFVCQ72K35WGIUMZYN3KOXIUXF2CNXWKG6ZWEZ6LT3NSF3XOQAC J44YLLLSMPKEY3IXV3CPOM257PQZW45A4QWSSBYVFXS5T5XGQQWAC KNO4TZR76DMOYJCF24PSVQW7FUZOTMOJTL7I7J74SM4IHOGDX6TAC Y5GWVQ5SM7DJEAPFOBPMMJH4D3NXBB2MPONSJUMG3KIQMBVGEE6AC 7X5YDPAU34LOFKEGJYE6GC7EOEDKGT3O6CUGZBYJI45L3FQOAKHQC FC7M3JHVRPOLZP7YWOJN4O6YJV7KRJUMPLTI2Q4ANCO7GD23YKWQC FLAGBNUNSIQNFDN53CDWABJRTTFWDL4PG34AI474ZKPXDEPYHOAQC 7YUGK5Q64KG5O7GJGTUBRRLHAHBCJ5YOE23YUPT6UBKUSB67CYAQC PI5BATR2SER3RFE76IUGHM2AGXVFOUM3PLU7WC2K2Q2BA5K2E73QC PHBACPMH3F34GODHVDKNCMXWU373RJQGVTDLBFCCDLLWDXVYOLTAC EJKHYV2Z6UPRVYUAL4WRW33GBNHYBFPMPA57HMBX2LQKXHIUO5VQC 46MRRHVYJ3BS74R2BEVUWEWJCI4FCRBSLZ3NWMQCE6FUCNE5P73QC PKXXBHS3LWLPZI2QVRX22MSQ4R2626IXRSNHFFYHXYTLJJQU54LQC FSJKED4U2SOUP64DTHF2NEGAYY7EUMSIDKC2SATEXAXEVOCNL3CAC T72EIKU4IJF3G3FBUDWMLMAFFUEF3ZNMKJFB5G3PZLFWH7W3H44AC // various elemental colour schemes... used for abstracting random// short lists. When adding colours, please also add their names in// initfile.cc (str_to_colour)!enum element_type{ETC_FIRE = 32, // fiery colours (must be first and > highest colour)ETC_ICE, // icy coloursETC_EARTH, // earthy coloursETC_ELECTRICITY, // electrical side of airETC_AIR, // non-electric and general air magicETC_POISON, // used only for venom mage and stalker stuffETC_WATER, // used only for the elementalETC_MAGIC, // general magical effectETC_MUTAGENIC, // transmute, poly, radiation effectsETC_WARP, // teleportation and anything similarETC_ENCHANT, // magical enhancementsETC_HEAL, // holy healing (not necromantic stuff)ETC_HOLY, // general "good" god effectsETC_DARK, // darknessETC_DEATH, // currently only assassin (and equal to ETC_NECRO)ETC_NECRO, // necromancy stuffETC_UNHOLY, // demonology stuffETC_VEHUMET, // vehumet's oddball coloursETC_BEOGH, // Beogh altar coloursETC_CRYSTAL, // colours of crystalETC_BLOOD, // colours of bloodETC_SMOKE, // colours of smokeETC_SLIME, // colours of slimeETC_JEWEL, // colourfulETC_ELVEN, // used for colouring elf fabric itemsETC_DWARVEN, // used for colouring dwarf fabric itemsETC_ORCISH, // used for colouring orc fabric itemsETC_GILA, // gila monster coloursETC_FLOOR, // colour of the area's floorETC_ROCK, // colour of the area's rockETC_STONE, // colour of the area's stoneETC_MIST, // colour of mistETC_SHIMMER_BLUE, // shimmering colours of blue.ETC_DECAY, // colour of decay/swampETC_SILVER, // colour of silverETC_GOLD, // colour of goldETC_IRON, // colour of ironETC_BONE, // colour of boneETC_RANDOM // any colour (except BLACK)};
void seed_rng();void seed_rng(long seed);void push_rng_state();void pop_rng_state();
void cf_setseed();bool coinflip();int div_rand_round( int num, int den );int div_round_up( int num, int den );bool one_chance_in(int a_million);bool x_chance_in_y(int x, int y);int random2(int max);int maybe_random2(int x, bool random_factor);int random_range(int low, int high);int random_range(int low, int high, int nrolls);const char* random_choose_string(const char* first, ...);int random_choose(int first, ...);int random_choose_weighted(int weight, int first, ...);unsigned long random_int();int random2avg(int max, int rolls);int bestroll(int max, int rolls);int roll_dice(int num, int size);void scale_dice(dice_def &dice, int threshold = 24);int binomial_generator(unsigned n_trials, unsigned trial_prob);// Various ways to iterate over things.
};class rectangle_iterator :public std::iterator<std::forward_iterator_tag, coord_def>{public:rectangle_iterator( const coord_def& corner1, const coord_def& corner2 );explicit rectangle_iterator( int x_border_dist, int y_border_dist = -1 );operator bool() const;coord_def operator *() const;const coord_def* operator->() const;rectangle_iterator& operator ++ ();rectangle_iterator operator ++ (int);private:coord_def current, topleft, bottomright;
class radius_iterator : public std::iterator<std::bidirectional_iterator_tag,coord_def>{public:radius_iterator( const coord_def& center, int radius,bool roguelike_metric = true,bool require_los = true,bool exclude_center = false,const env_show_grid* losgrid = NULL );bool done() const;void reset();operator bool() const { return !done(); }coord_def operator *() const;const coord_def* operator->() const;const radius_iterator& operator ++ ();const radius_iterator& operator -- ();radius_iterator operator ++ (int);radius_iterator operator -- (int);private:void step();void step_back();bool on_valid_square() const;coord_def location, center;int radius;bool roguelike_metric, require_los, exclude_center;const env_show_grid* losgrid;bool iter_done;};class adjacent_iterator : public radius_iterator{public:explicit adjacent_iterator( const coord_def& pos = you.pos(),bool _exclude_center = true ) :radius_iterator(pos, 1, true, false, _exclude_center) {}};int random2limit(int max, int limit);
bool in_bounds_x(int x);bool in_bounds_y(int y);bool in_bounds(int x, int y);bool map_bounds_x(int x);bool map_bounds_y(int y);bool map_bounds(int x, int y);coord_def random_in_bounds();inline bool in_bounds(const coord_def &p){return in_bounds(p.x, p.y);}inline bool map_bounds(const coord_def &p){return map_bounds(p.x, p.y);}// Determines if the coordinate is within bounds of an LOS array.inline bool show_bounds(const coord_def &p){return (p.x >= 0 && p.x < ENV_SHOW_DIAMETER&& p.y >= 0 && p.y < ENV_SHOW_DIAMETER);}int grid_distance( const coord_def& p1, const coord_def& p2 );int grid_distance( int x, int y, int x2, int y2 );int distance( const coord_def& p1, const coord_def& p2 );int distance( int x, int y, int x2, int y2);bool adjacent( const coord_def& p1, const coord_def& p2 );
unsigned char random_colour();unsigned char random_uncommon_colour();unsigned char make_low_colour(unsigned char colour);unsigned char make_high_colour(unsigned char colour);bool is_element_colour( int col );int element_colour( int element, bool no_random = false );
class rng_save_excursion{public:rng_save_excursion(long seed) { push_rng_state(); seed_rng(seed); }rng_save_excursion() { push_rng_state(); }~rng_save_excursion() { pop_rng_state(); }};template<typename Iterator>int choose_random_weighted(Iterator beg, const Iterator end){ASSERT(beg < end);#ifdef DEBUGint times_set = 0;#endifint totalweight = 0;int count = 0, result = 0;while (beg != end){totalweight += *beg;if (random2(totalweight) < *beg){result = count;#ifdef DEBUGtimes_set++;#endif}++count;++beg;}#ifdef DEBUGASSERT(times_set > 0);#endifreturn result;}
#endif#ifdef MORE_HARDENED_PRNG#include "sha256.h"#endif
}rectangle_iterator::rectangle_iterator( const coord_def& corner1,const coord_def& corner2 ){topleft.x = std::min(corner1.x, corner2.x);topleft.y = std::min(corner1.y, corner2.y); // not really necessarybottomright.x = std::max(corner1.x, corner2.x);bottomright.y = std::max(corner1.y, corner2.y);current = topleft;}rectangle_iterator::rectangle_iterator( int x_border_dist, int y_border_dist ){if (y_border_dist < 0)y_border_dist = x_border_dist;topleft.set(x_border_dist, y_border_dist);bottomright.set(GXM - x_border_dist - 1, GYM - y_border_dist - 1);current = topleft;
rectangle_iterator::operator bool() const{return (current.y <= bottomright.y);}coord_def rectangle_iterator::operator *() const{return current;}const coord_def* rectangle_iterator::operator->() const{return ¤t;}rectangle_iterator& rectangle_iterator::operator ++(){if (current.x == bottomright.x){current.x = topleft.x;current.y++;}else{current.x++;}return *this;}rectangle_iterator rectangle_iterator::operator++( int dummy ){const rectangle_iterator copy = *this;++(*this);return (copy);}radius_iterator::radius_iterator(const coord_def& _center, int _radius,bool _roguelike_metric, bool _require_los,bool _exclude_center,const env_show_grid* _losgrid): center(_center), radius(_radius), roguelike_metric(_roguelike_metric),require_los(_require_los), exclude_center(_exclude_center),losgrid(_losgrid), iter_done(false){reset();}void radius_iterator::reset(){iter_done = false;location.x = center.x - radius;location.y = center.y - radius;if ( !this->on_valid_square() )++(*this);}bool radius_iterator::done() const{return iter_done;}coord_def radius_iterator::operator *() const{return location;}const coord_def* radius_iterator::operator->() const{return &location;}void radius_iterator::step(){const int minx = std::max(X_BOUND_1+1, center.x - radius);const int maxx = std::min(X_BOUND_2-1, center.x + radius);const int maxy = std::min(Y_BOUND_2-1, center.y + radius);// Sweep L-R, U-Dlocation.x++;if (location.x > maxx){location.x = minx;location.y++;if (location.y > maxy)iter_done = true;}}void radius_iterator::step_back(){const int minx = std::max(X_BOUND_1+1, center.x - radius);const int maxx = std::min(X_BOUND_2-1, center.x + radius);const int miny = std::max(Y_BOUND_1+1, center.y - radius);location.x--;if (location.x < minx){location.x = maxx;location.y--;if (location.y < miny)iter_done = true;}}bool radius_iterator::on_valid_square() const{if (!in_bounds(location))return (false);if (!roguelike_metric && (location - center).abs() > radius*radius)return (false);if (require_los){if (!losgrid && !see_cell(location))return (false);if (losgrid && !see_cell(*losgrid, center, location))return (false);}if (exclude_center && location == center)return (false);return (true);}const radius_iterator& radius_iterator::operator++(){dothis->step();while (!this->done() && !this->on_valid_square());return (*this);}const radius_iterator& radius_iterator::operator--(){dothis->step_back();while (!this->done() && !this->on_valid_square());return (*this);}radius_iterator radius_iterator::operator++(int dummy){const radius_iterator copy = *this;++(*this);return (copy);}radius_iterator radius_iterator::operator--(int dummy){const radius_iterator copy = *this;--(*this);return (copy);}
void seed_rng(long seed){// MT19937 -- see mt19937ar.cc for details/licenceinit_genrand(seed);}void seed_rng(){unsigned long seed = time( NULL );#ifdef USE_MORE_SECURE_SEED/* (at least) 256-bit wide seed */unsigned long seed_key[8];struct tms buf;seed += times( &buf ) + getpid();seed_key[0] = seed;/* Try opening from various system provided (hopefully) CSPRNGs */FILE* seed_f = fopen("/dev/urandom", "rb");if (!seed_f)seed_f = fopen("/dev/random", "rb");if (!seed_f)seed_f = fopen("/dev/srandom", "rb");if (!seed_f)seed_f = fopen("/dev/arandom", "rb");if (seed_f){fread(&seed_key[1], sizeof(unsigned long), 7, seed_f);fclose(seed_f);}seed_rng(seed_key, 8);#elseseed_rng(seed);#endif}// MT19937 -- see mt19937ar.cc for detailsunsigned long random_int( void ){#ifndef MORE_HARDENED_PRNGreturn (genrand_int32());#elsereturn (sha256_genrand());#endif}int random_range(int low, int high){ASSERT(low <= high);return (low + random2(high - low + 1));}int random_range(int low, int high, int nrolls){ASSERT(nrolls > 0);int sum = 0;for (int i = 0; i < nrolls; ++i)sum += random_range(low, high);return (sum / nrolls);}// Chooses one of the numbers passed in at random. The list of numbers// must be terminated with -1.int random_choose(int first, ...){va_list args;va_start(args, first);int chosen = first, count = 1, nargs = 100;while (nargs-- > 0){const int pick = va_arg(args, int);if (pick == -1)break;if (one_chance_in(++count))chosen = pick;}ASSERT(nargs > 0);va_end(args);return (chosen);}// Chooses one of the strings passed in at random. The list of strings// must be terminated with NULL.const char* random_choose_string(const char* first, ...){va_list args;va_start(args, first);const char* chosen = first;int count = 1, nargs = 100;while (nargs-- > 0){char* pick = va_arg(args, char*);if (pick == NULL)break;if (one_chance_in(++count))chosen = pick;}ASSERT(nargs > 0);va_end(args);return (chosen);}int random_choose_weighted(int weight, int first, ...){va_list args;va_start(args, first);int chosen = first, cweight = weight, nargs = 100;while (nargs-- > 0){const int nweight = va_arg(args, int);if (!nweight)break;const int choice = va_arg(args, int);if (random2(cweight += nweight) < nweight)chosen = choice;}ASSERT(nargs > 0);va_end(args);return (chosen);}int random2(int max){if (max <= 1)return (0);#ifdef MORE_HARDENED_PRNGreturn (static_cast<int>(sha256_genrand() / (0xFFFFFFFFUL / max + 1)));#elsereturn (static_cast<int>(genrand_int32() / (0xFFFFFFFFUL / max + 1)));#endif}bool coinflip(void){return (static_cast<bool>(random2(2)));}// Returns random2(x) if random_factor is true, otherwise the mean.int maybe_random2(int x, bool random_factor){if (random_factor)return (random2(x));elsereturn (x / 2);}void push_rng_state(){push_mt_state();}void pop_rng_state(){pop_mt_state();}// Attempts to make missile weapons nicer to the player by reducing the// extreme variance in damage done.void scale_dice(dice_def &dice, int threshold){while (dice.size > threshold){dice.num *= 2;// If it's an odd number, lose one; this is more than// compensated by the increase in number of dice.dice.size /= 2;}}int bestroll(int max, int rolls){int best = 0;for (int i = 0; i < rolls; i++){int curr = random2(max);if (curr > best)best = curr;}return (best);}// random2avg() returns same mean value as random2() but with a lower variance// never use with rolls < 2 as that would be silly - use random2() instead {dlb}int random2avg(int max, int rolls){int sum = random2(max);for (int i = 0; i < (rolls - 1); i++)sum += random2(max + 1);return (sum / rolls);}int roll_dice(int num, int size){int ret = 0;int i;// If num <= 0 or size <= 0, then we'll just return the default// value of zero. This is good behaviour in that it will be// appropriate for calculated values that might be passed in.if (num > 0 && size > 0){ret += num; // since random2() is zero basedfor (i = 0; i < num; i++)ret += random2(size);}return (ret);}// originally designed to randomise evasion -// values are slightly lowered near (max) and// approach an upper limit somewhere near (limit/2)int random2limit(int max, int limit){int i;int sum = 0;if (max < 1)return (0);for (i = 0; i < max; i++)if (random2(limit) >= i)sum++;return (sum);}// Generate samples from a binomial distribution with n_trials and trial_prob// probability of success per trial. trial_prob is a integer less than 100// representing the % chancee of success.// This just evaluates all n trials, there is probably an efficient way of// doing this but I'm not much of a statistician. -CAOint binomial_generator(unsigned n_trials, unsigned trial_prob){int count = 0;for (unsigned i = 0; i < n_trials; ++i)if (::x_chance_in_y(trial_prob, 100))count++;return count;}
}// Calculates num/den and randomly adds one based on the remainder.int div_rand_round(int num, int den){return (num / den + (random2(den) < num % den));
}bool one_chance_in(int a_million){return (random2(a_million) == 0);}bool x_chance_in_y(int x, int y){if (x <= 0)return (false);if (x >= y)return (true);return (random2(y) < x);
int grid_distance( const coord_def& p1, const coord_def& p2 ){return grid_distance(p1.x, p1.y, p2.x, p2.y);}// More accurate than distance() given the actual movement geometry -- bwrint grid_distance( int x, int y, int x2, int y2 ){const int dx = abs( x - x2 );const int dy = abs( y - y2 );// returns distance in terms of moves:return ((dx > dy) ? dx : dy);}int distance( const coord_def& p1, const coord_def& p2 ){return distance(p1.x, p1.y, p2.x, p2.y);}int distance( int x, int y, int x2, int y2 ){//jmf: now accurate, but remember to only compare vs. pre-squared distances// thus, next to == (distance(m1.x,m1.y, m2.x,m2.y) <= 2)const int dx = x - x2;const int dy = y - y2;return ((dx * dx) + (dy * dy));}bool adjacent( const coord_def& p1, const coord_def& p2 ){return grid_distance(p1, p2) <= 1;}
}bool in_bounds_x(int x){return (x > X_BOUND_1 && x < X_BOUND_2);}bool in_bounds_y(int y){return (y > Y_BOUND_1 && y < Y_BOUND_2);}// Returns true if inside the area the player can move and dig (ie exclusive).bool in_bounds(int x, int y){return (in_bounds_x(x) && in_bounds_y(y));}bool map_bounds_x(int x){return (x >= X_BOUND_1 && x <= X_BOUND_2);}bool map_bounds_y(int y){return (y >= Y_BOUND_1 && y <= Y_BOUND_2);}// Returns true if inside the area the player can map (ie inclusive).// Note that terrain features should be in_bounds() leaving an outer// ring of rock to frame the level.bool map_bounds(int x, int y){return (map_bounds_x(x) && map_bounds_y(y));}coord_def random_in_bounds(){if (crawl_state.arena){const coord_def &ul = crawl_view.glos1; // Upper leftconst coord_def &lr = crawl_view.glos2; // Lower rightreturn coord_def(random_range(ul.x, lr.x - 1),random_range(ul.y, lr.y - 1));}elsereturn coord_def(random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1),random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1));}unsigned char random_colour(void){return (1 + random2(15));}unsigned char random_uncommon_colour(){unsigned char result;doresult = random_colour();while (result == LIGHTCYAN || result == CYAN || result == BROWN);return (result);}unsigned char make_low_colour(unsigned char colour){if (colour >= 8 && colour <= 15)return (colour - 8);return (colour);}unsigned char make_high_colour(unsigned char colour){if (colour <= 7)return (colour + 8);return (colour);}// returns if a colour is one of the special element colours (ie not regular)bool is_element_colour( int col ){// stripping any COLFLAGS (just in case)return ((col & 0x007f) >= ETC_FIRE);}int element_colour( int element, bool no_random ){// Doing this so that we don't have to do recursion here at all// (these were the only cases which had possible double evaluation):if (element == ETC_FLOOR)element = env.floor_colour;else if (element == ETC_ROCK)element = env.rock_colour;// pass regular colours through for safety.if (!is_element_colour( element ))return (element);int ret = BLACK;// Setting no_random to true will get the first colour in the cases// below. This is potentially useful for calls to this function// which might want a consistent result.int tmp_rand = (no_random ? 0 : random2(120));switch (element & 0x007f) // strip COLFLAGs just in case{case ETC_FIRE:ret = (tmp_rand < 40) ? RED :(tmp_rand < 80) ? YELLOW: LIGHTRED;break;case ETC_ICE:ret = (tmp_rand < 40) ? LIGHTBLUE :(tmp_rand < 80) ? BLUE: WHITE;break;case ETC_EARTH:ret = (tmp_rand < 60) ? BROWN : LIGHTRED;break;case ETC_AIR:ret = (tmp_rand < 60) ? LIGHTGREY : WHITE;break;case ETC_ELECTRICITY:ret = (tmp_rand < 40) ? LIGHTCYAN :(tmp_rand < 80) ? LIGHTBLUE: CYAN;break;case ETC_POISON:ret = (tmp_rand < 60) ? LIGHTGREEN : GREEN;break;case ETC_WATER:ret = (tmp_rand < 60) ? BLUE : CYAN;break;case ETC_MAGIC:ret = (tmp_rand < 30) ? LIGHTMAGENTA :(tmp_rand < 60) ? LIGHTBLUE :(tmp_rand < 90) ? MAGENTA: BLUE;break;case ETC_MUTAGENIC:case ETC_WARP:ret = (tmp_rand < 60) ? LIGHTMAGENTA : MAGENTA;break;case ETC_ENCHANT:ret = (tmp_rand < 60) ? LIGHTBLUE : BLUE;break;case ETC_HEAL:ret = (tmp_rand < 60) ? LIGHTBLUE : YELLOW;break;case ETC_BLOOD:ret = (tmp_rand < 60) ? RED : DARKGREY;break;case ETC_DEATH: // assassincase ETC_NECRO: // necromancerret = (tmp_rand < 80) ? DARKGREY : MAGENTA;break;case ETC_UNHOLY: // ie demonologyret = (tmp_rand < 80) ? DARKGREY : RED;break;case ETC_DARK:ret = (tmp_rand < 80) ? DARKGREY : LIGHTGREY;break;case ETC_HOLY:ret = (tmp_rand < 60) ? YELLOW : WHITE;break;case ETC_VEHUMET:ret = (tmp_rand < 40) ? LIGHTRED :(tmp_rand < 80) ? LIGHTMAGENTA: LIGHTBLUE;break;case ETC_BEOGH:ret = (tmp_rand < 60) ? LIGHTRED // plain Orc colour: BROWN; // Orcish mines wall/idol colourbreak;case ETC_CRYSTAL:ret = (tmp_rand < 40) ? LIGHTGREY :(tmp_rand < 80) ? GREEN: LIGHTRED;break;case ETC_SLIME:ret = (tmp_rand < 40) ? GREEN :(tmp_rand < 80) ? BROWN: LIGHTGREEN;break;case ETC_SMOKE:ret = (tmp_rand < 30) ? LIGHTGREY :(tmp_rand < 60) ? DARKGREY :(tmp_rand < 90) ? LIGHTBLUE: MAGENTA;break;case ETC_JEWEL:ret = (tmp_rand < 12) ? WHITE :(tmp_rand < 24) ? YELLOW :(tmp_rand < 36) ? LIGHTMAGENTA :(tmp_rand < 48) ? LIGHTRED :(tmp_rand < 60) ? LIGHTGREEN :(tmp_rand < 72) ? LIGHTBLUE :(tmp_rand < 84) ? MAGENTA :(tmp_rand < 96) ? RED :(tmp_rand < 108) ? GREEN: BLUE;break;case ETC_ELVEN:ret = (tmp_rand < 40) ? LIGHTGREEN :(tmp_rand < 80) ? GREEN :(tmp_rand < 100) ? LIGHTBLUE: BLUE;break;case ETC_DWARVEN:ret = (tmp_rand < 40) ? BROWN :(tmp_rand < 80) ? LIGHTRED :(tmp_rand < 100) ? LIGHTGREY: CYAN;break;case ETC_ORCISH:ret = (tmp_rand < 40) ? DARKGREY :(tmp_rand < 80) ? RED :(tmp_rand < 100) ? BROWN: MAGENTA;break;case ETC_GILA:ret = (tmp_rand < 30) ? LIGHTMAGENTA :(tmp_rand < 60) ? MAGENTA :(tmp_rand < 90) ? YELLOW :(tmp_rand < 105) ? LIGHTRED: RED;break;case ETC_STONE:if (player_in_branch( BRANCH_HALL_OF_ZOT ))ret = env.rock_colour;elseret = LIGHTGREY;break;case ETC_MIST:ret = tmp_rand < 100? CYAN : BLUE;break;case ETC_SHIMMER_BLUE:ret = random_choose_weighted(80, BLUE, 20, LIGHTBLUE, 5, CYAN, 0);break;case ETC_DECAY:ret = (tmp_rand < 60) ? BROWN : GREEN;break;case ETC_SILVER:ret = (tmp_rand < 90) ? LIGHTGREY : WHITE;break;case ETC_GOLD:ret = (tmp_rand < 60) ? YELLOW : BROWN;break;case ETC_IRON:ret = (tmp_rand < 40) ? CYAN :(tmp_rand < 80) ? LIGHTGREY :DARKGREY;break;case ETC_BONE:ret = (tmp_rand < 90) ? WHITE : LIGHTGREY;break;case ETC_RANDOM:ret = 1 + random2(15); // always randombreak;case ETC_FLOOR: // should already be handledcase ETC_ROCK: // should already be handleddefault:break;}ASSERT( !is_element_colour( ret ) );return ((ret == BLACK) ? GREEN : ret);
}int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage){const int lfuzz = lowfuzz * val / 100,hfuzz = highfuzz * val / 100;return val + random2avg(lfuzz + hfuzz + 1, naverage) - lfuzz;
//////////////////////////////////////////////////////////////////////////// coord_defint coord_def::distance_from(const coord_def &other) const{return (grid_distance(*this, other));}
#ifndef RNG_H#define RNG_Hvoid seed_rng();void seed_rng(long seed);void push_rng_state();void pop_rng_state();void cf_setseed();unsigned long random_int();#endif
/** File: rng.cc* Summary: Random number generator wrapping.*/#include "AppHdr.h"#include "rng.h"#include "mt19937ar.h"#ifdef USE_MORE_SECURE_SEED// for times()#include <sys/times.h>// for getpid()#include <sys/types.h>#include <unistd.h>#endif#ifdef MORE_HARDENED_PRNG#include "sha256.h"#endifvoid seed_rng(unsigned long* seed_key, size_t num_keys){// MT19937 -- see mt19937ar.cc for details/licenceinit_by_array(seed_key, num_keys);}void seed_rng(long seed){// MT19937 -- see mt19937ar.cc for details/licenceinit_genrand(seed);}void seed_rng(){unsigned long seed = time( NULL );#ifdef USE_MORE_SECURE_SEED/* (at least) 256-bit wide seed */unsigned long seed_key[8];struct tms buf;seed += times( &buf ) + getpid();seed_key[0] = seed;/* Try opening from various system provided (hopefully) CSPRNGs */FILE* seed_f = fopen("/dev/urandom", "rb");if (!seed_f)seed_f = fopen("/dev/random", "rb");if (!seed_f)seed_f = fopen("/dev/srandom", "rb");if (!seed_f)seed_f = fopen("/dev/arandom", "rb");if (seed_f){fread(&seed_key[1], sizeof(unsigned long), 7, seed_f);fclose(seed_f);}seed_rng(seed_key, 8);#elseseed_rng(seed);#endif}// MT19937 -- see mt19937ar.cc for detailsunsigned long random_int( void ){#ifndef MORE_HARDENED_PRNGreturn (genrand_int32());#elsereturn (sha256_genrand());#endif}void push_rng_state(){push_mt_state();}void pop_rng_state(){pop_mt_state();}
#ifndef RANDOM_H#define RANDOM_H#include "rng.h"bool coinflip();int div_rand_round( int num, int den );int div_round_up( int num, int den );bool one_chance_in(int a_million);bool x_chance_in_y(int x, int y);int random2(int max);int maybe_random2(int x, bool random_factor);int random_range(int low, int high);int random_range(int low, int high, int nrolls);const char* random_choose_string(const char* first, ...);int random_choose(int first, ...);int random_choose_weighted(int weight, int first, ...);int random2avg(int max, int rolls);int bestroll(int max, int rolls);int random2limit(int max, int limit);int binomial_generator(unsigned n_trials, unsigned trial_prob);int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage = 2);int roll_dice(int num, int size);struct dice_def{int num;int size;dice_def(int n = 0, int s = 0) : num(n), size(s) {}int roll() const;};dice_def calc_dice(int num_dice, int max_damage);void scale_dice(dice_def &dice, int threshold = 24);class rng_save_excursion{public:rng_save_excursion(long seed) { push_rng_state(); seed_rng(seed); }rng_save_excursion() { push_rng_state(); }~rng_save_excursion() { pop_rng_state(); }};template<typename Iterator>int choose_random_weighted(Iterator beg, const Iterator end){ASSERT(beg < end);#ifdef DEBUGint times_set = 0;#endifint totalweight = 0;int count = 0, result = 0;while (beg != end){totalweight += *beg;if (random2(totalweight) < *beg){result = count;#ifdef DEBUGtimes_set++;#endif}++count;++beg;}#ifdef DEBUGASSERT(times_set > 0);#endifreturn result;}#endif
#include "AppHdr.h"#include "random.h"int random_range(int low, int high){ASSERT(low <= high);return (low + random2(high - low + 1));}int random_range(int low, int high, int nrolls){ASSERT(nrolls > 0);int sum = 0;for (int i = 0; i < nrolls; ++i)sum += random_range(low, high);return (sum / nrolls);}// Chooses one of the numbers passed in at random. The list of numbers// must be terminated with -1.int random_choose(int first, ...){va_list args;va_start(args, first);int chosen = first, count = 1, nargs = 100;while (nargs-- > 0){const int pick = va_arg(args, int);if (pick == -1)break;if (one_chance_in(++count))chosen = pick;}ASSERT(nargs > 0);va_end(args);return (chosen);}// Chooses one of the strings passed in at random. The list of strings// must be terminated with NULL.const char* random_choose_string(const char* first, ...){va_list args;va_start(args, first);const char* chosen = first;int count = 1, nargs = 100;while (nargs-- > 0){char* pick = va_arg(args, char*);if (pick == NULL)break;if (one_chance_in(++count))chosen = pick;}ASSERT(nargs > 0);va_end(args);return (chosen);}int random_choose_weighted(int weight, int first, ...){va_list args;va_start(args, first);int chosen = first, cweight = weight, nargs = 100;while (nargs-- > 0){const int nweight = va_arg(args, int);if (!nweight)break;const int choice = va_arg(args, int);if (random2(cweight += nweight) < nweight)chosen = choice;}ASSERT(nargs > 0);va_end(args);return (chosen);}int random2(int max){if (max <= 1)return (0);return (static_cast<int>(random_int() / (0xFFFFFFFFUL / max + 1)));}bool coinflip(void){return (static_cast<bool>(random2(2)));}// Returns random2(x) if random_factor is true, otherwise the mean.int maybe_random2(int x, bool random_factor){if (random_factor)return (random2(x));elsereturn (x / 2);}int roll_dice(int num, int size){int ret = 0;int i;// If num <= 0 or size <= 0, then we'll just return the default// value of zero. This is good behaviour in that it will be// appropriate for calculated values that might be passed in.if (num > 0 && size > 0){ret += num; // since random2() is zero basedfor (i = 0; i < num; i++)ret += random2(size);}return (ret);}int dice_def::roll() const{return roll_dice(this->num, this->size);}dice_def calc_dice(int num_dice, int max_damage){dice_def ret(num_dice, 0);if (num_dice <= 1){ret.num = 1;ret.size = max_damage;}else if (max_damage <= num_dice){ret.num = max_damage;ret.size = 1;}else{// Divide the damage among the dice, and add one// occasionally to make up for the fractions. -- bwrret.size = max_damage / num_dice;ret.size += x_chance_in_y(max_damage % num_dice, num_dice);}return (ret);}// Attempts to make missile weapons nicer to the player by reducing the// extreme variance in damage done.void scale_dice(dice_def &dice, int threshold){while (dice.size > threshold){dice.num *= 2;// If it's an odd number, lose one; this is more than// compensated by the increase in number of dice.dice.size /= 2;}}// Calculates num/den and randomly adds one based on the remainder.int div_rand_round(int num, int den){return (num / den + (random2(den) < num % den));}int bestroll(int max, int rolls){int best = 0;for (int i = 0; i < rolls; i++){int curr = random2(max);if (curr > best)best = curr;}return (best);}// random2avg() returns same mean value as random2() but with a lower variance// never use with rolls < 2 as that would be silly - use random2() instead {dlb}int random2avg(int max, int rolls){int sum = random2(max);for (int i = 0; i < (rolls - 1); i++)sum += random2(max + 1);return (sum / rolls);}// originally designed to randomise evasion -// values are slightly lowered near (max) and// approach an upper limit somewhere near (limit/2)int random2limit(int max, int limit){int i;int sum = 0;if (max < 1)return (0);for (i = 0; i < max; i++)if (random2(limit) >= i)sum++;return (sum);}// Generate samples from a binomial distribution with n_trials and trial_prob// probability of success per trial. trial_prob is a integer less than 100// representing the % chancee of success.// This just evaluates all n trials, there is probably an efficient way of// doing this but I'm not much of a statistician. -CAOint binomial_generator(unsigned n_trials, unsigned trial_prob){int count = 0;for (unsigned i = 0; i < n_trials; ++i)if (::x_chance_in_y(trial_prob, 100))count++;return count;}bool one_chance_in(int a_million){return (random2(a_million) == 0);}bool x_chance_in_y(int x, int y){if (x <= 0)return (false);if (x >= y)return (true);return (random2(y) < x);}int fuzz_value(int val, int lowfuzz, int highfuzz, int naverage){const int lfuzz = lowfuzz * val / 100,hfuzz = highfuzz * val / 100;return val + random2avg(lfuzz + hfuzz + 1, naverage) - lfuzz;}
#ifdef USE_TILEstatic std::string tile_cols[24] ={"black", "darkgrey", "grey", "lightgrey", "white","blue", "lightblue", "darkblue","green", "lightgreen", "darkgreen","cyan", "lightcyan", "darkcyan","red", "lightred", "darkred","magenta", "lightmagenta", "darkmagenta","yellow", "lightyellow", "darkyellow", "brown"};static unsigned int _str_to_tile_colour(std::string colour){if (colour.empty())return (0);
lowercase(colour);if (colour == "darkgray")colour = "darkgrey";else if (colour == "gray")colour = "grey";else if (colour == "lightgray")colour = "lightgrey";for (unsigned int i = 0; i < 24; i++){if (tile_cols[i] == colour)return (i);}return (0);}#endifconst std::string cols[16] ={"black", "blue", "green", "cyan", "red", "magenta", "brown","lightgrey", "darkgrey", "lightblue", "lightgreen", "lightcyan","lightred", "lightmagenta", "yellow", "white"};const std::string colour_to_str(unsigned char colour){if ( colour >= 16 )return "lightgrey";elsereturn cols[colour];}
int str_to_colour( const std::string &str, int default_colour,bool accept_number ){int ret;static const std::string element_cols[] ={"fire", "ice", "earth", "electricity", "air", "poison","water", "magic", "mutagenic", "warp", "enchant", "heal","holy", "dark", "death", "necro", "unholy", "vehumet","beogh", "crystal", "blood", "smoke", "slime", "jewel","elven", "dwarven", "orcish", "gila", "floor", "rock","stone", "mist", "shimmer_blue", "decay", "silver", "gold","iron", "bone", "random"};ASSERT(ARRAYSZ(element_cols) == (ETC_RANDOM - ETC_FIRE) + 1);for (ret = 0; ret < 16; ++ret){if (str == cols[ret])break;}// Check for alternate spellings.if (ret == 16){if (str == "lightgray")ret = 7;else if (str == "darkgray")ret = 8;}if (ret == 16){// Maybe we have an element colour attribute.for (unsigned i = 0; i < sizeof(element_cols) / sizeof(*element_cols);++i){if (str == element_cols[i]){// Ugh.ret = element_type(ETC_FIRE + i);break;}}}if (ret == 16 && accept_number){// Check if we have a direct colour index.const char *s = str.c_str();char *es = NULL;const int ci = static_cast<int>(strtol(s, &es, 10));if (s != (const char *) es && es && ci >= 0 && ci < 16)ret = ci;}return ((ret == 16) ? default_colour : ret);}// Returns -1 if unmatched else returns 0-15.
struct dice_def{int num;int size;dice_def( int n = 0, int s = 0 ) : num(n), size(s) {}int roll() const;};
#ifndef COORDIT_H#define COORDIT_H#include "player.h"class rectangle_iterator :public std::iterator<std::forward_iterator_tag, coord_def>{public:rectangle_iterator( const coord_def& corner1, const coord_def& corner2 );explicit rectangle_iterator( int x_border_dist, int y_border_dist = -1 );operator bool() const;coord_def operator *() const;const coord_def* operator->() const;rectangle_iterator& operator ++ ();rectangle_iterator operator ++ (int);private:coord_def current, topleft, bottomright;};class radius_iterator : public std::iterator<std::bidirectional_iterator_tag,coord_def>{public:radius_iterator( const coord_def& center, int radius,bool roguelike_metric = true,bool require_los = true,bool exclude_center = false,const env_show_grid* losgrid = NULL );bool done() const;void reset();operator bool() const { return !done(); }coord_def operator *() const;const coord_def* operator->() const;const radius_iterator& operator ++ ();const radius_iterator& operator -- ();radius_iterator operator ++ (int);radius_iterator operator -- (int);private:void step();void step_back();bool on_valid_square() const;coord_def location, center;int radius;bool roguelike_metric, require_los, exclude_center;const env_show_grid* losgrid;bool iter_done;};class adjacent_iterator : public radius_iterator{public:explicit adjacent_iterator( const coord_def& pos = you.pos(),bool _exclude_center = true ) :radius_iterator(pos, 1, true, false, _exclude_center) {}};#endif
/** File: coordit.h* Summary: Coordinate iterators.*/#include "AppHdr.h"#include "coordit.h"#include "coord.h"#include "los.h"rectangle_iterator::rectangle_iterator( const coord_def& corner1,const coord_def& corner2 ){topleft.x = std::min(corner1.x, corner2.x);topleft.y = std::min(corner1.y, corner2.y); // not really necessarybottomright.x = std::max(corner1.x, corner2.x);bottomright.y = std::max(corner1.y, corner2.y);current = topleft;}rectangle_iterator::rectangle_iterator( int x_border_dist, int y_border_dist ){if (y_border_dist < 0)y_border_dist = x_border_dist;topleft.set(x_border_dist, y_border_dist);bottomright.set(GXM - x_border_dist - 1, GYM - y_border_dist - 1);current = topleft;}rectangle_iterator::operator bool() const{return (current.y <= bottomright.y);}coord_def rectangle_iterator::operator *() const{return current;}const coord_def* rectangle_iterator::operator->() const{return ¤t;}rectangle_iterator& rectangle_iterator::operator ++(){if (current.x == bottomright.x){current.x = topleft.x;current.y++;}else{current.x++;}return *this;}rectangle_iterator rectangle_iterator::operator++( int dummy ){const rectangle_iterator copy = *this;++(*this);return (copy);}radius_iterator::radius_iterator(const coord_def& _center, int _radius,bool _roguelike_metric, bool _require_los,bool _exclude_center,const env_show_grid* _losgrid): center(_center), radius(_radius), roguelike_metric(_roguelike_metric),require_los(_require_los), exclude_center(_exclude_center),losgrid(_losgrid), iter_done(false){reset();}void radius_iterator::reset(){iter_done = false;location.x = center.x - radius;location.y = center.y - radius;if ( !this->on_valid_square() )++(*this);}bool radius_iterator::done() const{return iter_done;}coord_def radius_iterator::operator *() const{return location;}const coord_def* radius_iterator::operator->() const{return &location;}void radius_iterator::step(){const int minx = std::max(X_BOUND_1+1, center.x - radius);const int maxx = std::min(X_BOUND_2-1, center.x + radius);const int maxy = std::min(Y_BOUND_2-1, center.y + radius);// Sweep L-R, U-Dlocation.x++;if (location.x > maxx){location.x = minx;location.y++;if (location.y > maxy)iter_done = true;}}void radius_iterator::step_back(){const int minx = std::max(X_BOUND_1+1, center.x - radius);const int maxx = std::min(X_BOUND_2-1, center.x + radius);const int miny = std::max(Y_BOUND_1+1, center.y - radius);location.x--;if (location.x < minx){location.x = maxx;location.y--;if (location.y < miny)iter_done = true;}}bool radius_iterator::on_valid_square() const{if (!in_bounds(location))return (false);if (!roguelike_metric && (location - center).abs() > radius*radius)return (false);if (require_los){if (!losgrid && !see_cell(location))return (false);if (losgrid && !see_cell(*losgrid, center, location))return (false);}if (exclude_center && location == center)return (false);return (true);}const radius_iterator& radius_iterator::operator++(){dothis->step();while (!this->done() && !this->on_valid_square());return (*this);}const radius_iterator& radius_iterator::operator--(){dothis->step_back();while (!this->done() && !this->on_valid_square());return (*this);}radius_iterator radius_iterator::operator++(int dummy){const radius_iterator copy = *this;++(*this);return (copy);}radius_iterator radius_iterator::operator--(int dummy){const radius_iterator copy = *this;--(*this);return (copy);}
#ifndef COORD_H#define COORD_Hbool in_bounds_x(int x);bool in_bounds_y(int y);bool in_bounds(int x, int y);bool map_bounds_x(int x);bool map_bounds_y(int y);bool map_bounds(int x, int y);coord_def random_in_bounds();inline bool in_bounds(const coord_def &p){return in_bounds(p.x, p.y);}inline bool map_bounds(const coord_def &p){return map_bounds(p.x, p.y);}// Determines if the coordinate is within bounds of an LOS array.inline bool show_bounds(const coord_def &p){return (p.x >= 0 && p.x < ENV_SHOW_DIAMETER&& p.y >= 0 && p.y < ENV_SHOW_DIAMETER);}int grid_distance( const coord_def& p1, const coord_def& p2 );int grid_distance( int x, int y, int x2, int y2 );int distance( const coord_def& p1, const coord_def& p2 );int distance( int x, int y, int x2, int y2);bool adjacent( const coord_def& p1, const coord_def& p2 );#endif
#include "AppHdr.h"#include "coord.h"#include "directn.h"#include "random.h"#include "state.h"//////////////////////////////////////////////////////////////////////////// coord_defint coord_def::distance_from(const coord_def &other) const{return (grid_distance(*this, other));}int grid_distance( const coord_def& p1, const coord_def& p2 ){return grid_distance(p1.x, p1.y, p2.x, p2.y);}// More accurate than distance() given the actual movement geometry -- bwrint grid_distance( int x, int y, int x2, int y2 ){const int dx = abs( x - x2 );const int dy = abs( y - y2 );// returns distance in terms of moves:return ((dx > dy) ? dx : dy);}int distance( const coord_def& p1, const coord_def& p2 ){return distance(p1.x, p1.y, p2.x, p2.y);}int distance( int x, int y, int x2, int y2 ){//jmf: now accurate, but remember to only compare vs. pre-squared distances// thus, next to == (distance(m1.x,m1.y, m2.x,m2.y) <= 2)const int dx = x - x2;const int dy = y - y2;return ((dx * dx) + (dy * dy));}bool adjacent( const coord_def& p1, const coord_def& p2 ){return grid_distance(p1, p2) <= 1;}bool in_bounds_x(int x){return (x > X_BOUND_1 && x < X_BOUND_2);}bool in_bounds_y(int y){return (y > Y_BOUND_1 && y < Y_BOUND_2);}// Returns true if inside the area the player can move and dig (ie exclusive).bool in_bounds(int x, int y){return (in_bounds_x(x) && in_bounds_y(y));}bool map_bounds_x(int x){return (x >= X_BOUND_1 && x <= X_BOUND_2);}bool map_bounds_y(int y){return (y >= Y_BOUND_1 && y <= Y_BOUND_2);}// Returns true if inside the area the player can map (ie inclusive).// Note that terrain features should be in_bounds() leaving an outer// ring of rock to frame the level.bool map_bounds(int x, int y){return (map_bounds_x(x) && map_bounds_y(y));}coord_def random_in_bounds(){if (crawl_state.arena){const coord_def &ul = crawl_view.glos1; // Upper leftconst coord_def &lr = crawl_view.glos2; // Lower rightreturn coord_def(random_range(ul.x, lr.x - 1),random_range(ul.y, lr.y - 1));}elsereturn coord_def(random_range(MAPGEN_BORDER, GXM - MAPGEN_BORDER - 1),random_range(MAPGEN_BORDER, GYM - MAPGEN_BORDER - 1));}
#ifndef COLOUR_H#define COLOUR_H// various elemental colour schemes... used for abstracting random// short lists. When adding colours, please also add their names in// str_to_colour!enum element_type{ETC_FIRE = 32, // fiery colours (must be first and > highest colour)ETC_ICE, // icy coloursETC_EARTH, // earthy coloursETC_ELECTRICITY, // electrical side of airETC_AIR, // non-electric and general air magicETC_POISON, // used only for venom mage and stalker stuffETC_WATER, // used only for the elementalETC_MAGIC, // general magical effectETC_MUTAGENIC, // transmute, poly, radiation effectsETC_WARP, // teleportation and anything similarETC_ENCHANT, // magical enhancementsETC_HEAL, // holy healing (not necromantic stuff)ETC_HOLY, // general "good" god effectsETC_DARK, // darknessETC_DEATH, // currently only assassin (and equal to ETC_NECRO)ETC_NECRO, // necromancy stuffETC_UNHOLY, // demonology stuffETC_VEHUMET, // vehumet's oddball coloursETC_BEOGH, // Beogh altar coloursETC_CRYSTAL, // colours of crystalETC_BLOOD, // colours of bloodETC_SMOKE, // colours of smokeETC_SLIME, // colours of slimeETC_JEWEL, // colourfulETC_ELVEN, // used for colouring elf fabric itemsETC_DWARVEN, // used for colouring dwarf fabric itemsETC_ORCISH, // used for colouring orc fabric itemsETC_GILA, // gila monster coloursETC_FLOOR, // colour of the area's floorETC_ROCK, // colour of the area's rockETC_STONE, // colour of the area's stoneETC_MIST, // colour of mistETC_SHIMMER_BLUE, // shimmering colours of blue.ETC_DECAY, // colour of decay/swampETC_SILVER, // colour of silverETC_GOLD, // colour of goldETC_IRON, // colour of ironETC_BONE, // colour of boneETC_RANDOM // any colour (except BLACK)};int str_to_colour(const std::string &str, int default_colour = -1,bool accept_number = true);const std::string colour_to_str(unsigned char colour);unsigned int str_to_tile_colour(std::string colour);unsigned char random_colour();unsigned char random_uncommon_colour();unsigned char make_low_colour(unsigned char colour);unsigned char make_high_colour(unsigned char colour);bool is_element_colour(int col);int element_colour(int element, bool no_random = false);#endif
#include "AppHdr.h"#include "colour.h"#include "env.h"#include "player.h"#include "random.h"unsigned char random_colour(void){return (1 + random2(15));}unsigned char random_uncommon_colour(){unsigned char result;doresult = random_colour();while (result == LIGHTCYAN || result == CYAN || result == BROWN);return (result);}unsigned char make_low_colour(unsigned char colour){if (colour >= 8 && colour <= 15)return (colour - 8);return (colour);}unsigned char make_high_colour(unsigned char colour){if (colour <= 7)return (colour + 8);return (colour);}// returns if a colour is one of the special element colours (ie not regular)bool is_element_colour( int col ){// stripping any COLFLAGS (just in case)return ((col & 0x007f) >= ETC_FIRE);}int element_colour( int element, bool no_random ){// Doing this so that we don't have to do recursion here at all// (these were the only cases which had possible double evaluation):if (element == ETC_FLOOR)element = env.floor_colour;else if (element == ETC_ROCK)element = env.rock_colour;// pass regular colours through for safety.if (!is_element_colour( element ))return (element);int ret = BLACK;// Setting no_random to true will get the first colour in the cases// below. This is potentially useful for calls to this function// which might want a consistent result.int tmp_rand = (no_random ? 0 : random2(120));switch (element & 0x007f) // strip COLFLAGs just in case{case ETC_FIRE:ret = (tmp_rand < 40) ? RED :(tmp_rand < 80) ? YELLOW: LIGHTRED;break;case ETC_ICE:ret = (tmp_rand < 40) ? LIGHTBLUE :(tmp_rand < 80) ? BLUE: WHITE;break;case ETC_EARTH:ret = (tmp_rand < 60) ? BROWN : LIGHTRED;break;case ETC_AIR:ret = (tmp_rand < 60) ? LIGHTGREY : WHITE;break;case ETC_ELECTRICITY:ret = (tmp_rand < 40) ? LIGHTCYAN :(tmp_rand < 80) ? LIGHTBLUE: CYAN;break;case ETC_POISON:ret = (tmp_rand < 60) ? LIGHTGREEN : GREEN;break;case ETC_WATER:ret = (tmp_rand < 60) ? BLUE : CYAN;break;case ETC_MAGIC:ret = (tmp_rand < 30) ? LIGHTMAGENTA :(tmp_rand < 60) ? LIGHTBLUE :(tmp_rand < 90) ? MAGENTA: BLUE;break;case ETC_MUTAGENIC:case ETC_WARP:ret = (tmp_rand < 60) ? LIGHTMAGENTA : MAGENTA;break;case ETC_ENCHANT:ret = (tmp_rand < 60) ? LIGHTBLUE : BLUE;break;case ETC_HEAL:ret = (tmp_rand < 60) ? LIGHTBLUE : YELLOW;break;case ETC_BLOOD:ret = (tmp_rand < 60) ? RED : DARKGREY;break;case ETC_DEATH: // assassincase ETC_NECRO: // necromancerret = (tmp_rand < 80) ? DARKGREY : MAGENTA;break;case ETC_UNHOLY: // ie demonologyret = (tmp_rand < 80) ? DARKGREY : RED;break;case ETC_DARK:ret = (tmp_rand < 80) ? DARKGREY : LIGHTGREY;break;case ETC_HOLY:ret = (tmp_rand < 60) ? YELLOW : WHITE;break;case ETC_VEHUMET:ret = (tmp_rand < 40) ? LIGHTRED :(tmp_rand < 80) ? LIGHTMAGENTA: LIGHTBLUE;break;case ETC_BEOGH:ret = (tmp_rand < 60) ? LIGHTRED // plain Orc colour: BROWN; // Orcish mines wall/idol colourbreak;case ETC_CRYSTAL:ret = (tmp_rand < 40) ? LIGHTGREY :(tmp_rand < 80) ? GREEN: LIGHTRED;break;case ETC_SLIME:ret = (tmp_rand < 40) ? GREEN :(tmp_rand < 80) ? BROWN: LIGHTGREEN;break;case ETC_SMOKE:ret = (tmp_rand < 30) ? LIGHTGREY :(tmp_rand < 60) ? DARKGREY :(tmp_rand < 90) ? LIGHTBLUE: MAGENTA;break;case ETC_JEWEL:ret = (tmp_rand < 12) ? WHITE :(tmp_rand < 24) ? YELLOW :(tmp_rand < 36) ? LIGHTMAGENTA :(tmp_rand < 48) ? LIGHTRED :(tmp_rand < 60) ? LIGHTGREEN :(tmp_rand < 72) ? LIGHTBLUE :(tmp_rand < 84) ? MAGENTA :(tmp_rand < 96) ? RED :(tmp_rand < 108) ? GREEN: BLUE;break;case ETC_ELVEN:ret = (tmp_rand < 40) ? LIGHTGREEN :(tmp_rand < 80) ? GREEN :(tmp_rand < 100) ? LIGHTBLUE: BLUE;break;case ETC_DWARVEN:ret = (tmp_rand < 40) ? BROWN :(tmp_rand < 80) ? LIGHTRED :(tmp_rand < 100) ? LIGHTGREY: CYAN;break;case ETC_ORCISH:ret = (tmp_rand < 40) ? DARKGREY :(tmp_rand < 80) ? RED :(tmp_rand < 100) ? BROWN: MAGENTA;break;case ETC_GILA:ret = (tmp_rand < 30) ? LIGHTMAGENTA :(tmp_rand < 60) ? MAGENTA :(tmp_rand < 90) ? YELLOW :(tmp_rand < 105) ? LIGHTRED: RED;break;case ETC_STONE:if (player_in_branch( BRANCH_HALL_OF_ZOT ))ret = env.rock_colour;elseret = LIGHTGREY;break;case ETC_MIST:ret = tmp_rand < 100? CYAN : BLUE;break;case ETC_SHIMMER_BLUE:ret = random_choose_weighted(80, BLUE, 20, LIGHTBLUE, 5, CYAN, 0);break;case ETC_DECAY:ret = (tmp_rand < 60) ? BROWN : GREEN;break;case ETC_SILVER:ret = (tmp_rand < 90) ? LIGHTGREY : WHITE;break;case ETC_GOLD:ret = (tmp_rand < 60) ? YELLOW : BROWN;break;case ETC_IRON:ret = (tmp_rand < 40) ? CYAN :(tmp_rand < 80) ? LIGHTGREY :DARKGREY;break;case ETC_BONE:ret = (tmp_rand < 90) ? WHITE : LIGHTGREY;break;case ETC_RANDOM:ret = 1 + random2(15); // always randombreak;case ETC_FLOOR: // should already be handledcase ETC_ROCK: // should already be handleddefault:break;}ASSERT( !is_element_colour( ret ) );return ((ret == BLACK) ? GREEN : ret);}#ifdef USE_TILEstatic std::string tile_cols[24] ={"black", "darkgrey", "grey", "lightgrey", "white","blue", "lightblue", "darkblue","green", "lightgreen", "darkgreen","cyan", "lightcyan", "darkcyan","red", "lightred", "darkred","magenta", "lightmagenta", "darkmagenta","yellow", "lightyellow", "darkyellow", "brown"};unsigned int str_to_tile_colour(std::string colour){if (colour.empty())return (0);lowercase(colour);if (colour == "darkgray")colour = "darkgrey";else if (colour == "gray")colour = "grey";else if (colour == "lightgray")colour = "lightgrey";for (unsigned int i = 0; i < 24; i++){if (tile_cols[i] == colour)return (i);}return (0);}#endifconst std::string cols[16] ={"black", "blue", "green", "cyan", "red", "magenta", "brown","lightgrey", "darkgrey", "lightblue", "lightgreen", "lightcyan","lightred", "lightmagenta", "yellow", "white"};const std::string colour_to_str(unsigned char colour){if ( colour >= 16 )return "lightgrey";elsereturn cols[colour];}// Returns -1 if unmatched else returns 0-15.int str_to_colour( const std::string &str, int default_colour,bool accept_number ){int ret;static const std::string element_cols[] ={"fire", "ice", "earth", "electricity", "air", "poison","water", "magic", "mutagenic", "warp", "enchant", "heal","holy", "dark", "death", "necro", "unholy", "vehumet","beogh", "crystal", "blood", "smoke", "slime", "jewel","elven", "dwarven", "orcish", "gila", "floor", "rock","stone", "mist", "shimmer_blue", "decay", "silver", "gold","iron", "bone", "random"};ASSERT(ARRAYSZ(element_cols) == (ETC_RANDOM - ETC_FIRE) + 1);for (ret = 0; ret < 16; ++ret){if (str == cols[ret])break;}// Check for alternate spellings.if (ret == 16){if (str == "lightgray")ret = 7;else if (str == "darkgray")ret = 8;}if (ret == 16){// Maybe we have an element colour attribute.for (unsigned i = 0; i < sizeof(element_cols) / sizeof(*element_cols);++i){if (str == element_cols[i]){// Ugh.ret = element_type(ETC_FIRE + i);break;}}}if (ret == 16 && accept_number){// Check if we have a direct colour index.const char *s = str.c_str();char *es = NULL;const int ci = static_cast<int>(strtol(s, &es, 10));if (s != (const char *) es && es && ci >= 0 && ci < 16)ret = ci;}return ((ret == 16) ? default_colour : ret);}
}dice_def calc_dice( int num_dice, int max_damage ){dice_def ret( num_dice, 0 );if (num_dice <= 1){ret.num = 1;ret.size = max_damage;}else if (max_damage <= num_dice){ret.num = max_damage;ret.size = 1;}else{// Divide the damage among the dice, and add one// occasionally to make up for the fractions. -- bwrret.size = max_damage / num_dice;ret.size += x_chance_in_y(max_damage % num_dice, num_dice);}return (ret);