Allow hydra zombies (they currently do not get the right number of heads).
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4872 c06c8d41-db1a-0410-9941-cceddc491573
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
EPR4MQUMXA4US62JU6FYSGMQFMLA5UGLVO4FE633IAEOJHLLTUWQC
73NSMIRFFRXAEBDKSENC3DDOKAGSVNVE3MYTFT5AJQUIJKBOTR6QC
V2GHSFQQJE3UCWDDFLPB66TR5RPJBXKU5ENSKGW3JBDRC4PDDKEAC
DOP4ZWBT26AXTY5P3JZVGHEUI64KNUKFGP2ISBAXKULOP53TXGPAC
DXJADYFUIHZ2AIURSQK5RKWSXL3CF3NXZNM2KBR76EDM54EEBRLAC
226KYCTMLIXUKD734QATY3JKWUUKC5Q3O75JT5EWIX6BKR7ANZSAC
ASZZQSS6PJCN4OEQ7ZNHQ6WVGZRF2IKRJUMPA2TYQNBURPSUKQGAC
YO7TE72UUQA22IZVAYEFAKVFC24Q3AMVUQZHQGKVKKM34T52TJZAC
JD3FMKAAAUQZSNPGFLVX7F5H5SWGUSYOFZU4X5W4XYNV6HUKDBKAC
EWERG2OANAMC7ZHWNPLFJB5ICT67T44S7PPAU4J24NU3AL7KK74AC
LEGFIEUGVU2LZELGQH4TZTIJGKEVUHFTRGQ4Y2KGLSK7KNDI7BFQC
NIJDQAJEWQIYKPDWIXYCCT4JIWVE6CWJ3J3K4N5PPGHWENGNZZXQC
Q4S2HEQNQZUN6Q2LIX36URDANVAYBMRWUTEDANKXFICOBGMCEGDAC
TONFKA6OUHKQVVN7LP6QR4LHODWBCZQ6V42ITUO6EI4SW642A7PAC
WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC
QEPTJOPJFKTXH27KOHY7DMQSMTXWAM57OPL3Y7WYE4X2OFMZE5IAC
XKWPTINAGPP4MXVIIYFOGQZPK53KSDZ4VZHVORJBOXC7XB3WUCLQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
OTNE6MGPNEJRKXEC36SEFYFZOHD3GPOQZGZC7DBYFG6W5JQ345KQC
5MGUZD2UACJCSG74TEZHI3Z4YL5KL6ZVUCQ3XVZKDOLKM7EMGWJAC
K64KYSPAKMNST3HQU25PF5BLVBC2I556MLBWUL7H7GHWKBGAUJIAC
UKBVBVJK23OUOOKQJRGLZWEZYED5KZ4NLODW6U67UEBYCFWGGQOAC
7G4KWTOOBRLHOZZGFGAXGTUCDF3FGSZOXVHUZZ3V2KVWYSFE7EKAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
AM7QPHDAWNXHLUEVUHVRHG2RO2DOIEFFU4GV3DCIROW6O5HW7H4AC
7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
DH3YTI6VVI727SQXO4CXSDCSBG2UN3UAWLFULBGRLBVH22ACRXIAC
IE3INS4WUXZOBVXB5VWRBYPVPXADD2U2W5H3TBTOYNWJ3EGRSGQQC
PZFEPJU6AYNJRZ2UM3GLBJHPH7MBNGPBM6GBSLI2BKZ4JJNGCYVAC
X4OCLD5YEXCYVQNMOQORLIO72AKUEMT3BT6FB3TW2HARKN5X7MEQC
AREBCIU2RU2RNHBWD4GARWEBKSL7HDFGDLII22H56OJO2AQUOMLQC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
RDXVYNDERZPFQYVM6TAPCKWLDM7SB4JLYX6PYDVEQBX4SEVQOAHQC
7YUGK5Q64KG5O7GJGTUBRRLHAHBCJ5YOE23YUPT6UBKUSB67CYAQC
C7EEMEI6FU6L2VWZBTDCZO5ZTB2N5TCNGSMIBZTN6NZRE7BUBFPQC
VRSBPOOVRUXKIP6HQPVZ3ZY2N2TFRUF2GOZM2CA6PXUM5IJTCY2QC
SJXOZ6J66G3S5VYGIZ3YHEUCKUF5554YEFUYLVBH7X4ALYSXKTGQC
TXF4NRVICF3RMD3VQARDJKGOGBGIJNO6FKOV5POTF73XQHNB6WVAC
UHOAWBSBZBPHWMNXZCVB4SBJM4DTZAG3YRNNJNIKJN4CE2DP27JQC
UABPE6GY5LDGEUPJVH6K7DNWQRAEQ4DXPB2NNM45SI47QYFV2XOQC
4SUG4IBPRQSAGEWNR4BVHMJV5MJRQUYXI4OZ5YXAZUSLF4CVKX2AC
U3KGUJJQWQORJIIFH3ADVNIEEX5HOX6KEOXO7DJSL7L3Z6GG3PAQC
TS7X6ZTTQRB2I53VV4LXZPXZWM3DIKYI3T5PPHZANSEW4Q7QZBOAC
MSMWAL6JZAWNGZXCNXPATUMAU6TVXBWWFY666P7UBSZ5LPYJYUCQC
3HMZIQCJSWUYTWQDWRQYPI5VOSRIAGGBOM7LIMF7362RJ2LRMZAAC
CRU7JBTVJWTTVQ5JTRA2B3X2FPKPJ2RRR33IK2OG536VMOEZJYJAC
2TFYJ7D72JY4DYQW3GSPEONA2WYIVHAJXTIQ2QRDIWF65XN2QFGAC
3MAPXTL5GAQ6373CUUVPBARIRHBRSISAF3BO2WBEROT2KUAXWLGAC
CA6ZG6P2CE5EPAOQSB3P7NBDKTNFFHQP4CPOUFZL32ON6N32GSSQC
SWOYPTHJAWFEDBMB3ROT33VQZIXGZD5UOXEV456DDUENW2HGA66QC
G2EYUPAIPISVAEG26BS3SQANL37EEZJ3TZBJKKWHGKQ66LB3RFQAC
L4PKJZERR7WADKWHY3MR6J6OZFREVPL3CB43I6MLJ2BVKWCUTE7AC
SS6MUIJYTGIVBYU356Z563QJWLJ47QNHSJWS7GJTS7EATZH2ESJQC
KYVZGUJXV23ELA4CKPVQZO3NTJCODXMCWYAZJYWVWJVLPETNHLGQC
P2OYYNPHIBGOLT4CRLNTTIXDN34EU2QCMFQJNLAMUAHQXZTEDPXQC
DDU4A3JGN5IUIPP5IASOODKPR2WBHSDSV4FITZ6HNXNSXXQACWAQC
BGJ7P65JV2OFVXMGAJDHV5Y36TR7JOFDWJUZJBHUBD7SCQMDRBEAC
LFRMK2FWZEWOABNM3T36YKBSUTNUA6DDTSBEFEMHM5KOFJBL5M7QC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
KEYK3CH5J46U6TTOKTWRNMYTZXMQXFVEAZUC4ZQ4QCOSJHVIBDRQC
MX2KOWAIE37VLSQJWXVEDVQVB3DL325Q7YFUSSHYMAIH53Y74IJQC
IXOB6KSQY3CWTXS3LLNDWLVMNK6CV2MCXJAR5CJLNNX4ZOLAMV6QC
VOR2QOT3R3BC3H74GMW4PUBY77QBJXE5QGQNBIINBE3MPSH6CXWQC
47NSOFQMBZCDIBHEAZSENFUGDSQCX3GJHFBUZ65ARDKCYIZ435LAC
V7IKAPO5OY7CJTT62GMHQOD3EQW42FTTY3KDBOTJUODPS5WMBCHAC
L254F6ZIU2HWGLFFGPIORTN4C3TDQ3E5JZ7Z7GQA5AEDIKL6PKDAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
I7NXCEKCEBDWOGO7EDNRZ36GELP3P5GTOOXQG2YS5TXZTCNN7CDQC
XAFFD52IHN6FWFR2TT5F2KCUS7HAVCBI5CWTFMKPQG77GGTGAHLAC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
ODNAIEJW732NG7USKQKCIP4R4DAEYXXJQX6LY7TIN32NKE75454QC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
3C2VE43SHCSBY4LTRTFYFLIPRWFUN6DXU6D34QVWDQTSNRBUFG7AC
22MF6OUN62WDBJR5QFNJTKU7Q5TIQ76XWCEIRBFWAZDMZUSKJGCAC
TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC
ID373JATLMWAY526Q6Q5FXHRNFWMEOFXPHGPAUUY5OAMPFDN5SJAC
WDEFQ6YABDQIGJXW5KT3OGR3EO6FZHXZELIRVIXQ4XDYTVOV5V6AC
2TECJQA3PK7OYSSTOWZSQFWMTATJRHHA6JV3IGRHFGS3R7U27RZAC
QUFPPRIIRXHUFEDH3EFES7CSHTA7GG2DAXTRHUAUQBYMSWK4BP6AC
C22455VGUQOSUX2OORA32LROFQ7NNYDMD2ZDTTUZSAQLXK4AD6QAC
AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
5B5DP5S6A6LQMKZYVLQAEMHQZWFWYDHPCKQGRNSCNNYIBQYZ6BIQC
RTNOP7F7GOYLE4V7R5JP5PJJDSMMOAPRTPDCSZOJVEPK6PO6SIWQC
F7Q5PX44SLPANIZXCY67TG2W5JTRVJMHGQW54VJLGB4XRH7R6JBQC
LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC
6L4EP4ZRWWYLT55PD5KTTJON5J2JB5VV5MWNHF5VPZQZ5BKEYZ4QC
5V47S4NNTHWTSAHV3YLO2VGH7JTUIYJ3GBPDN5ZM4UQALT2ZEXDQC
UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
6GSPAIEMWJXYSCR5EC2WBOGYDEDR6ESIZC6TKN2FVE2CVPSHUHXAC
GQL5SIGBHLU3FMCE54XVGLRY5AZHRM6DUEB722REA2DPLGJSN6EQC
FEAW5HX4TFYOEGUNSESIV5IB2Z65XEJ2EALW6PYNTPRLTPT7APUAC
3V52MSSK7QX7FWLLUW63DTWCBAJEK674EFZLKP45FLZ5KZKVARHAC
YZXHBEKWQPY4BTKG5FFGLP3AIRBQSTKQVLJJHWKQEA3HTN4UHDYQC
TZMLB4SJENS4JWIPIG7HFOFRIOZYYH5YB4TG7ZGBYT63C5B3MXDQC
ISSEUTHG7EH3QTFLS23GXFIOQXCI5HJPJMK6GWNFMC6NDRD2H34QC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
K2MLPJIAXXZRWEWZCNSGICCBNIU2WAAPT7SPIMOH7FLLTOB4QFRAC
JJULXW764V5C2HJKZNWQAEWB6QM5YZADD7ZCE35LYTBFEM6PMYCAC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
UWI3ZNJDRQRL7CXFNFEG46TA6SAK24XUFY5YOKVOTJA3VG3OBNFAC
OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC
3WHI3KM43ZCN4ITJLFQQBQBC4OJPRS7QTBPIQ6QBCUVKRSK476SAC
WMHFDQKUDCUGM3R245LLVZ5NNEZSCXFDSTNMVS2O5EFUHHO7HU3AC
WW6THKR7JN447YC23YYHYYNH7ABMCFFSECNUFTIJBZX6JHX6W7TAC
GRH4XPIYHDOXXF3R3QPMZTFHGLO2OJAZS4FLNBBXG3DHTQQM7RDQC
7YSKYUNV34XIWRTJUHJV4QMQRTXXYDIXM5AZSPSDPAYDW4B4PU6QC
APGCKU4AFOV7Z7XIEO5A27H4IFUGDU227I3Z7OIRROYSLOFFBJ5AC
EH4VJW3I5Y4V6DT3YMLNDA3NW2DEAV4LRE4T5IEXAVB4WB3JJMGAC
A3CO4KBFTFU3ZSHWRY2OPPX3MMTFV7OUCZGL7Q4Y2FU7JO4AP7MAC
TMN6MGCYNMQL3GG5P3JKKT4ROF2RB26H4AE6LHNEE76MBRVCDZMQC
KT3JMGSH5VTNRV2H5POWZLYNXSIRE5CT2XW3ZID7FNZTXYOZG22QC
G6WNKWA4GNUGNOH63AKXJQMQS2V4FGJ55CB4P2Z3MPSX3UPMVF6AC
6UU6TNVACSJT4JM7WOAE5XXTGUBV3QDDB5ANBFVYMULTHE7UMELQC
ACKNLTFL2RI3PMRWLNRVLRWGQAMLRFKNGNS5LED6NFE5GVGFIHFAC
5UC5TI7B6NWGIGN74QRBZKDBYUMHLM2ZO5ATXEZ6TZOGOLF3JX5QC
NWJ5IHZJXYE4I7CKSDNMTLGTIKOWK42LC2UYZL2TLXSZLM67WKRAC
IVVTHLTTLOP5TSULXJWUSSXHOKYWVU3OWKYVK45A7RIB6V34MYQAC
L4RYVF46EQKMVOEADGRG4WMPVTQ6NNFGYMU4SHAH6XJIKWVHT77QC
HIRKGUMNJPWKSVTR6TVBPD3MWNA63CEHCLCIPWEMGDFHVB3NPLDQC
75M6AVUSS3G5EJECJJRB67V5UYDOIV26FZNB2FFCMBZ33EK7FVIQC
FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
CCMBDS5S4KEI4LJTVBFDDEGWRTWM4GQB2GLEUUT7TMQRXFLZ4HXQC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
IIK2W5J4NQWD3BVXPJDUCTONSF2ENXPSZBWMZCBC25RCTNMKSK6AC
JNB3PBPBJHDUHH47ZICB25QENPTMLYK7CXC5BXRVWZ3J3ZZPKCUAC
45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
KKROXTUPBNEXXEUUDJNADATK3BCQPSQWFZ6L4VTKBPTYXJLYUHDQC
ILN2K6ASDZSMEHOPJ22IZLZJUO6DDGZTKAKXM3YXG6JZZHJNLX4AC
JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC
NTFA3ZSJFTVLTTKI6ONJE33PGGDW36IVGWMO6GXRA4ZG57TOWNFAC
OY7KHQPESOUHPBXRZ2JSNUKPAC7DCDY73TAUHCSJG5V6TPAHBVYQC
AOLWOUIFBQDQTCMSVB7N7GAKFUY5J5LH7CJZAY3HEY3WEUSLADZAC
LJK4ZQATLSB4MKZG3ARZX5V6RFGTN3NLCN6GTCUGJQKU26SOXMUAC
QYQKV4R47PTERXVFQNNWWQVICGSOMBHW6WM5TAZAKLIYOLLPUAJAC
6ME4TYV7ITXCAUMNVB27LRRHB72J2FVVZMJNS34IMAN57R37AE2QC
CNTH672RXIVHXRTZQ5MB4SDZKVQI3J5B6AD6PLUPONCTY7IDDMZAC
35KOQQV4ZBNNIAXGKPOYHOWTN7RBQY7HRZTVMR3WAS4GOYFBM6PQC
EWQIUA5WOC7YATFBBYEC4FM3V36MPM44EEDIMR4NU2DEUCSB2GSAC
VEOWM6UDFNWRAXP5YUO7XBH4ZALAJXCWRA4IRDITXJ3QWH42CTWAC
JIMH7VEMQ7QF6VV2D65UISCRG5W55UX5YSQLLUW6SZNSTZMFWQ5AC
MWA35QHODXDNH2OYJ3URQQOXSEONHFXY4OG4VMGHYBBTAC777NLQC
6LYLJJDKKIPIXKJITRAC7LAZSNBO7O4IJIVBKUC7FD57AV53LHHAC
YCL3W2PFE6ILTGBFODCSXNPDIA46KVSZP2TI7HDMYAOEJT65RIEAC
VRFQK6S2TXOFFO5K5HRDXPR7QEKKAZAVCASSIJVPWQ4GE26UOGTQC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
NRMSQFTORG3GC7HQBIN5DHB5GLWXM6IQO6PTXD4C7LBQWJIHYIGAC
QL5YCGGNXVNGD5WACTFKXQOUCCXOKMUQGRHDJAUEIW25LQUSTD2QC
if (create_monster(xom_random_demon(sever, one_chance_in(8)),
0, beh, you.x_pos, you.y_pos,
you.pet_target, MONS_PROGRAM_BUG) != -1)
if (create_monster(
mgen_data(xom_random_demon(sever, one_chance_in(8)),
beh, 0, you.pos(), you.pet_target)) != -1)
{
// Number of heads
int heads = mon->number;
if (heads > 7) heads = 7;
return TILE_MONS_HYDRA + heads - 1;
}
// Number of heads
return TILE_MONS_HYDRA + std::min(mon->number, 7) - 1;
create_monster( RANDOM_MONSTER, 2, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG );
create_monster(
mgen_data( RANDOM_MONSTER, BEH_FRIENDLY, 2,
you.pos(), you.pet_target ));
if (create_monster( summon_any_demon(DEMON_LESSER), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG ) != -1)
if (create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
BEH_HOSTILE, 5, you.pos(), MHITYOU)) != -1)
create_monster( MONS_SPATIAL_VORTEX, 3,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data(MONS_SPATIAL_VORTEX,
BEH_HOSTILE, 3,
you.pos(), MHITYOU));
if (create_monster( summon_any_demon(DEMON_COMMON), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG) != -1)
if (create_monster(
mgen_data(summon_any_demon(DEMON_COMMON),
BEH_HOSTILE, 5,
you.pos(), MHITYOU)) != -1)
create_monster( summon_any_demon(DEMON_LESSER), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
BEH_HOSTILE, 5, you.pos(), MHITYOU));
create_monster( summon_any_demon(DEMON_LESSER), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
BEH_HOSTILE, 5, you.pos(), MHITYOU));
{
create_monster( summon_any_demon(DEMON_LESSER), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
}
create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
BEH_HOSTILE, 5, you.pos(), MHITYOU));
{
create_monster( summon_any_demon(DEMON_LESSER), 5,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
}
create_monster(
mgen_data(summon_any_demon(DEMON_LESSER),
BEH_HOSTILE, 5, you.pos(), MHITYOU));
if (create_monster( summon_any_demon(DEMON_GREATER), 0,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG ) != -1)
if (create_monster(
mgen_data::alert_hostile_at(
summon_any_demon(DEMON_GREATER),
you.pos())) != -1)
create_monster( summon_any_demon(DEMON_COMMON), 3,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data::alert_hostile_at(
summon_any_demon(DEMON_COMMON), you.pos(), 3));
create_monster( summon_any_demon(DEMON_COMMON), 3,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data::alert_hostile_at(
summon_any_demon(DEMON_COMMON), you.pos(), 3));
{
create_monster(summon_any_demon(DEMON_COMMON), 3,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG);
}
create_monster(
mgen_data::alert_hostile_at(
summon_any_demon(DEMON_COMMON), you.pos(), 3));
{
create_monster( MONS_SHADOW, 2, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU,
MONS_PROGRAM_BUG );
}
create_monster(
mgen_data::alert_hostile_at(
MONS_SHADOW, you.pos(), 2));
{
create_monster( MONS_SHADOW, 2, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU,
MONS_PROGRAM_BUG );
}
create_monster(
mgen_data::alert_hostile_at(
MONS_SHADOW, you.pos(), 2));
create_monster( MONS_BUTTERFLY, 3, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG, false, false,
false, true );
create_monster(
mgen_data(MONS_BUTTERFLY, BEH_FRIENDLY, 3,
you.pos(), you.pet_target));
if (create_monster( mon, dur, beha,
you.x_pos, you.y_pos, hitting,
MONS_PROGRAM_BUG, false, false,
false, true ) != -1)
if (create_monster(
mgen_data( mon, beha, dur,
you.pos(), hitting )) != -1)
if (create_monster( MONS_DRAGON, 3,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true ) != -1)
if (create_monster(
mgen_data( MONS_DRAGON,
friendly ? BEH_FRIENDLY : BEH_HOSTILE, 3,
you.pos(),
friendly ? you.pet_target : MHITYOU )) != -1)
// int mon = create_monster( MONS_BALL_LIGHTNING, 0, BEH_FRIENDLY,
// tx, ty, MHITNOT, MONS_PROGRAM_BUG );
int mon =
mons_place(
mgen_data( MONS_BALL_LIGHTNING, BEH_FRIENDLY, 0,
coord_def(tx, ty) ));
void make_shuggoth(int x, int y, int hp)
{
int mon = create_monster( MONS_SHUGGOTH, 100 + random2avg(58, 3),
BEH_HOSTILE, x, y, MHITNOT, MONS_PROGRAM_BUG,
false, false, false, true );
if (mon != -1)
{
menv[mon].hit_points = hp;
menv[mon].max_hit_points = hp;
}
return;
} // end make_shuggoth()
if (create_monster( MONS_SIMULACRUM_SMALL, 6,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, mons_type ) != -1)
if (create_monster(
mgen_data(MONS_SIMULACRUM_SMALL,
BEH_FRIENDLY, 6,
you.pos(), you.pet_target,
0, mons_type)) != -1)
if (create_monster( type_summoned, numsc,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
targ_x, targ_y,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true ) == -1)
if (create_monster(
mgen_data( type_summoned,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
numsc,
coord_def(targ_x, targ_y),
friendly ? you.pet_target : MHITYOU )) != -1)
create_monster( thing_called, 3, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG, false, false, false, true);
create_monster(
mgen_data( thing_called, BEH_FRIENDLY, 3,
you.pos(), you.pet_target ));
create_monster( mon_chosen, 4,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false, false, true);
create_monster(
mgen_data( mon_chosen,
friendly ? BEH_FRIENDLY : BEH_HOSTILE, 4,
you.pos(),
friendly ? you.pet_target : MHITYOU ));
if (create_monster( MONS_SCORPION, 3,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true) != -1)
if (create_monster(
mgen_data(MONS_SCORPION,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
3,
you.pos(),
friendly ? you.pet_target : MHITYOU)) != -1)
if (create_monster(ugly, numsc,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true) != -1)
if (create_monster(
mgen_data(ugly,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
numsc,
you.pos(),
friendly ? you.pet_target : MHITYOU)) != -1)
int monster = create_monster( ibc, numsc, beha,
you.x_pos, you.y_pos, hitting,
MONS_PROGRAM_BUG, false, false,
false, true );
int monster =
create_monster(
mgen_data(ibc, beha, numsc,
you.pos(), hitting));
int mons = create_monster( mon, numsc, beha, you.x_pos, you.y_pos,
god_gift ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG );
int mons =
create_monster(
mgen_data( mon, beha, numsc,
you.pos(),
god_gift ? you.pet_target : MHITYOU ));
if (create_monster( thing_called, 3, behaviour,
you.x_pos, you.y_pos,
!unfriendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true ) != -1)
if (create_monster(
mgen_data( thing_called, behaviour, 3,
you.pos(),
!unfriendly ? you.pet_target : MHITYOU )) != -1)
if (create_monster( thing_called, 5,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false,
false, true ) != -1)
if (create_monster(
mgen_data(thing_called,
friendly ? BEH_FRIENDLY : BEH_HOSTILE, 5,
you.pos(),
friendly ? you.pet_target : MHITYOU)) != -1)
create_monster( MONS_TENTACLED_MONSTROSITY, 6, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG, false, false, false, true );
create_monster(
mgen_data(MONS_TENTACLED_MONSTROSITY, BEH_FRIENDLY, 6,
you.pos(), you.pet_target));
create_monster( MONS_ABOMINATION_LARGE, 6, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG, false, false, false, true );
create_monster(
mgen_data(MONS_ABOMINATION_LARGE, BEH_FRIENDLY, 6,
you.pos(), you.pet_target ));
const bool success = create_monster(MONS_EXECUTIONER + random2(5), 0,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG) != -1;
const bool success =
create_monster(
mgen_data(
static_cast<monster_type>(
MONS_EXECUTIONER + random2(5)),
BEH_HOSTILE, 0,
you.pos(), MHITYOU)) != -1;
if (create_monster(MONS_NEQOXEC + random2(5), 0, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU,
MONS_PROGRAM_BUG) != -1)
if (create_monster(
mgen_data(
static_cast<monster_type>(
MONS_NEQOXEC + random2(5)),
BEH_HOSTILE, 0,
you.pos(), MHITYOU)) != -1)
if (create_monster(MONS_GREEN_DEATH + random2(3), 0,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG) != -1)
if (create_monster(
mgen_data::alert_hostile_at(
static_cast<monster_type>(MONS_GREEN_DEATH + random2(3)),
you.pos())) != -1)
if (create_monster(MONS_NEQOXEC + random2(5), 0, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU,
MONS_PROGRAM_BUG) != -1)
if (create_monster(
mgen_data::alert_hostile_at(
static_cast<monster_type>(MONS_NEQOXEC + random2(5)),
you.pos())) != -1)
create_monster( which_mons, duration,
SAME_ATTITUDE(monster), monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data( which_mons, SAME_ATTITUDE(monster), duration,
monster->pos(), monster->foe ));
create_monster( mons, 5, SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data( mons, SAME_ATTITUDE(monster), 5,
monster->pos(), monster->foe ) );
create_monster( RANDOM_MONSTER, 5, SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data( RANDOM_MONSTER, SAME_ATTITUDE(monster), 5,
monster->pos(), monster->foe ) );
create_monster( MONS_RAKSHASA_FAKE, 3,
SAME_ATTITUDE(monster), monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data( MONS_RAKSHASA_FAKE, SAME_ATTITUDE(monster), 3,
monster->pos(), monster->foe ) );
create_monster( mons, duration, SAME_ATTITUDE(monster),
monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data( mons, SAME_ATTITUDE(monster), duration,
monster->pos(), monster->foe ) );
create_monster( summon_any_demon(DEMON_LESSER), duration,
SAME_ATTITUDE(monster), monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data( summon_any_demon(DEMON_LESSER),
SAME_ATTITUDE(monster),
duration, monster->pos(),
monster->foe ));
create_monster( MONS_UFETUBUS, duration, SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data(MONS_UFETUBUS, SAME_ATTITUDE(monster), duration,
monster->pos(), monster->foe));
create_monster( MONS_BEAST, 4, SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data(MONS_BEAST, SAME_ATTITUDE(monster), 4,
monster->pos(), monster->foe));
create_monster( MONS_ICE_BEAST, 5, SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data(MONS_ICE_BEAST, SAME_ATTITUDE(monster), 5,
monster->pos(), monster->foe));
create_monster(MONS_WANDERING_MUSHROOM, duration,
SAME_ATTITUDE(monster),
monster->x, monster->y,
monster->foe,
MONS_PROGRAM_BUG);
create_monster(
mgen_data(MONS_WANDERING_MUSHROOM,
SAME_ATTITUDE(monster),
duration,
monster->pos(),
monster->foe));
create_monster( summon_any_demon(DEMON_GREATER), duration,
SAME_ATTITUDE(monster), monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data(summon_any_demon(DEMON_GREATER),
SAME_ATTITUDE(monster),
duration,
monster->pos(),
monster->foe));
create_monster( monsters[i], duration,
SAME_ATTITUDE(monster),
monster->x, monster->y, monster->foe,
MONS_PROGRAM_BUG );
create_monster(
mgen_data(monsters[i], SAME_ATTITUDE(monster), duration,
monster->pos(), monster->foe));
create_monster( summon_any_demon((coinflip() ? DEMON_COMMON
: DEMON_LESSER)),
5, BEH_HOSTILE,
you.x_pos, you.y_pos,
MHITYOU, MONS_PROGRAM_BUG );
create_monster(
mgen_data(
summon_any_demon((coinflip() ? DEMON_COMMON
: DEMON_LESSER)),
BEH_HOSTILE, 5, you.pos(), MHITYOU ));
if (create_monster( MONS_SPECTRAL_THING, 0, BEH_FRIENDLY,
monster->x, monster->y, you.pet_target,
mons_species(monster->type)) != -1)
if (create_monster(
mgen_data( MONS_SPECTRAL_THING, BEH_FRIENDLY,
0, monster->pos(), you.pet_target,
0, mons_species(monster->type) )) != -1)
create_monster( MONS_ABOMINATION_SMALL, 2,
SAME_ATTITUDE(monster), monster->x, monster->y,
monster->foe, MONS_PROGRAM_BUG );
create_monster(
mgen_data(MONS_ABOMINATION_SMALL, SAME_ATTITUDE(monster),
2, monster->pos(), monster->foe) );
};
enum mgen_flag_type
{
MG_PERMIT_BANDS = 0x1,
MG_FORCE_PLACE = 0x2,
MG_FORCE_BEH = 0x4,
MG_PLAYER_MADE = 0x8
};
// A structure with all the data needed to whip up a new monster.
struct mgen_data
{
// Monster type.
monster_type cls;
// If the monster is zombie-like, or a specialised draconian, this
// is the base monster that the monster is based on - should be
// set to MONS_PROGRAM_BUG when not used.
monster_type base_type;
// Determines the behaviour of the monster after it is generated. This
// behaviour is an unholy combination of monster attitude
// (friendly, hostile) and monster initial state (asleep, wandering).
// XXX: Could use splitting up these aspects.
beh_type behaviour;
// For summoned monsters, this is a measure of how long the summon will
// hang around, on a scale of 1-6, 6 being longest. Use 0 for monsters
// that aren't summoned.
int abjuration_duration;
// Where the monster will be created.
coord_def pos;
// The monster's foe, i.e. which monster it will want to attack. foe
// may be an index into the monster array (0 - (MAX_MONSTERS-1)), or
// it may be MHITYOU to indicate that the monster wants to attack the
// player, or MHITNOT, to indicate that the monster has no foe and is
// just wandering around.
int foe;
// Generation flags from mgen_flag_type.
unsigned flags;
// The number of hydra heads or manticore attack volleys. Note:
// in older version this field was used for both this and for base_type.
int number;
// The colour of the monster
int colour;
// A measure of how powerful the generated monster should be (for
// randomly chosen monsters), usually equal to the absolute depth
// that the player is in the dungeon.
int power;
// How close to or far from the player the monster should be created.
// Is usually used only when the initial position (pos) is unspecified.
proximity_type proximity;
// What place we're in, or pretending to be in, usually the place
// the player is actually in.
level_area_type level_type;
// Some predefined vaults (aka maps) include flags to suppress random
// generation of monsters. When generating monsters, this is a mask of
// map flags to honour (such as MMT_NO_MONS to specify that we shouldn't
// randomly generate a monster inside a map that doesn't want it). These
// map flags are usually respected only when a dungeon level is being
// constructed, since at future points vault information may no longer
// be available (vault metadata is not preserved across game saves).
unsigned map_mask;
mgen_data(monster_type mt = RANDOM_MONSTER,
beh_type beh = BEH_HOSTILE,
int abj = 0,
const coord_def &p = coord_def(-1, -1),
int mfoe = MHITNOT,
unsigned monflags = 0,
monster_type base = MONS_PROGRAM_BUG,
int monnumber = 0,
int moncolour = BLACK,
int monpower = you.your_level,
proximity_type prox = PROX_ANYWHERE,
level_area_type ltype = you.level_type)
: cls(mt), base_type(base), behaviour(beh),
abjuration_duration(abj), pos(p), foe(mfoe), flags(monflags),
number(monnumber), colour(moncolour), power(monpower),
proximity(prox), level_type(ltype), map_mask(0)
{
}
bool permit_bands() const { return (flags & MG_PERMIT_BANDS); }
bool force_place() const { return (flags & MG_FORCE_PLACE); }
// Is there a valid position set on this struct that we want to use
// when placing the monster?
bool use_position() const { return in_bounds(pos); }
bool summoned() const { return (abjuration_duration > 0); }
static mgen_data sleeper_at(monster_type what,
const coord_def &where)
{
return mgen_data(what, BEH_SLEEP, 0, where);
}
static mgen_data hostile_at(monster_type what,
const coord_def &where)
{
return mgen_data(what, BEH_HOSTILE, 0, where);
}
static mgen_data alert_hostile_at(monster_type what,
const coord_def &where,
int abj_deg = 0)
{
return mgen_data(what, BEH_HOSTILE, abj_deg, where, MHITYOU);
}
int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
int px, int py, int level_type = LEVEL_DUNGEON,
proximity_type proximity = PROX_ANYWHERE,
int extra = MONS_PROGRAM_BUG,
int dur = 0, bool permit_bands = false );
int mons_place( mgen_data mg );
/* int mons_place( int mon_type, beh_type behaviour, int target, bool summoned, */
/* int px, int py, int level_type = LEVEL_DUNGEON, */
/* proximity_type proximity = PROX_ANYWHERE, */
/* int extra = MONS_PROGRAM_BUG, */
/* int dur = 0, bool permit_bands = false ); */
int create_monster( mgen_data mg );
int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y,
int hitting, int zsec, bool permit_bands = false,
bool force_place = false, bool force_behaviour = false,
bool player_made = false );
/* int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y, */
/* int hitting, int zsec, bool permit_bands = false, */
/* bool force_place = false, bool force_behaviour = false, */
/* bool player_made = false ); */
bool place_monster( int &id, int mon_type, int power, beh_type behaviour,
int target, bool summoned, int px, int py, bool allow_bands,
proximity_type proximity = PROX_ANYWHERE,
int extra = MONS_PROGRAM_BUG, int dur = 0,
unsigned mmask = 0 );
int place_monster( mgen_data mg );
// int &id, int mon_type, int power, beh_type behaviour,
// int target, bool summoned, int px, int py, bool allow_bands,
// proximity_type proximity = PROX_ANYWHERE,
// int extra = MONS_PROGRAM_BUG, int dur = 0,
// unsigned mmask = 0 );
static int place_monster_aux(int mon_type, beh_type behaviour, int target,
int px, int py, int power, int extra,
bool first_band_member, int dur = 0);
// static int _place_monster_aux(int mon_type, beh_type behaviour, int target,
// int px, int py, int power, int extra,
// bool first_band_member, int dur = 0);
static int resolve_monster_type(int mon_type, proximity_type proximity,
int num, int px, int py, unsigned mmask,
dungeon_char_type *stair_type,
int *lev_mons)
static monster_type resolve_monster_type(monster_type mon_type,
proximity_type proximity,
monster_type base_type,
coord_def &pos,
unsigned mmask,
dungeon_char_type *stair_type,
int *lev_mons)
random_range(MONS_BLACK_DRACONIAN, MONS_DRACONIAN_SCORCHER);
while (num != MONS_PROGRAM_BUG
&& mon_type != num
static_cast<monster_type>(
random_range(MONS_BLACK_DRACONIAN,
MONS_DRACONIAN_SCORCHER));
while (base_type != MONS_PROGRAM_BUG
&& mon_type != base_type
if (mons_class_is_stationary( mon_type )
|| pval == 2
&& (mons_speed(mon_type) == 0 || grd[px][py] == DNGN_LAVA
|| grd[px][py] == DNGN_DEEP_WATER))
if (mons_class_is_stationary( mg.cls )
|| (pval == 2
&& (mons_speed(mg.cls) == 0 || grd(mg.pos) == DNGN_LAVA
|| grd(mg.pos) == DNGN_DEEP_WATER)))
// handled above, won't change anymore
if (proximity == PROX_NEAR_STAIRS && tries)
{
proximity = PROX_AWAY_FROM_PLAYER;
tries = 0;
}
case PROX_ANYWHERE:
if (grid_distance( you.x_pos, you.y_pos, px, py ) < 2 + random2(3))
{
proxOK = false;
}
break;
case PROX_ANYWHERE:
if (grid_distance( you.x_pos, you.y_pos,
mg.pos.x, mg.pos.y ) < 2 + random2(3))
{
proxOK = false;
}
break;
case PROX_CLOSE_TO_PLAYER:
case PROX_AWAY_FROM_PLAYER:
close_to_player = (distance(you.x_pos, you.y_pos, px, py) < 64);
case PROX_CLOSE_TO_PLAYER:
case PROX_AWAY_FROM_PLAYER:
close_to_player =
(distance(you.x_pos, you.y_pos,
mg.pos.x, mg.pos.y) < 64);
if (mg.proximity == PROX_CLOSE_TO_PLAYER && !close_to_player
|| mg.proximity == PROX_AWAY_FROM_PLAYER && close_to_player)
{
proxOK = false;
}
break;
if (proximity == PROX_CLOSE_TO_PLAYER && !close_to_player
|| proximity == PROX_AWAY_FROM_PLAYER && close_to_player)
case PROX_NEAR_STAIRS:
if (pval == 2) // player on stairs
{
// 0 speed monsters can't shove player out of their way.
if (mons_speed(mg.cls) == 0)
break;
case PROX_NEAR_STAIRS:
if (pval == 2) // player on stairs
// swap the monster and the player spots, unless the
// monster was generated in lava or deep water.
if (grd(mg.pos) == DNGN_LAVA ||
grd(mg.pos) == DNGN_DEEP_WATER)
// 0 speed monsters can't shove player out of their way.
if (mons_speed(mon_type) == 0)
{
proxOK = false;
break;
}
// swap the monster and the player spots, unless the
// monster was generated in lava or deep water.
if (grd[px][py] == DNGN_LAVA || grd[px][py] == DNGN_DEEP_WATER)
{
proxOK = false;
break;
}
shoved = true;
int tpx = px;
int tpy = py;
px = you.x_pos;
py = you.y_pos;
you.moveto(tpx, tpy);
proxOK = false;
break;
// now, forget about banding if the first placement failed, or there's too
// many monsters already, or we successfully placed by stairs
if (id < 0 || id+30 > MAX_MONSTERS)
return false;
// Bail out now if we failed.
if (id == -1)
return (id);
// monsters placed by stairs don't bring the whole band up/down/through
// with them
if (proximity == PROX_NEAR_STAIRS)
return (true);
// now, forget about banding if the first placement failed, or there's too
// many monsters already, or we successfully placed by stairs
if (id >= MAX_MONSTERS - 30 || mg.proximity == PROX_NEAR_STAIRS)
return (id);
static int place_monster_aux( int mon_type, beh_type behaviour, int target,
int px, int py, int power, int extra,
bool first_band_member, int dur )
static int _place_monster_aux( const mgen_data &mg,
bool first_band_member )
} // end place_monster_aux()
}
static monster_type _pick_random_zombie()
{
static std::vector<monster_type> zombifiable;
if (zombifiable.empty())
{
for (int i = 0; i < NUM_MONSTERS; ++i)
{
if (mons_species(i) != i || i == MONS_PROGRAM_BUG)
continue;
const monster_type mcls = static_cast<monster_type>(i);
if (!mons_zombie_size(mcls))
continue;
zombifiable.push_back(mcls);
}
}
return (zombifiable[ random2(zombifiable.size()) ]);
}
static void _define_zombie( int mid, monster_type ztype,
monster_type cs, int power )
{
monster_type mons_sec2 = MONS_PROGRAM_BUG;
int zombie_size = 0;
bool ignore_rarity = false;
monster_type cls = MONS_PROGRAM_BUG;
if (power > 27)
power = 27;
// set size based on zombie class (cs)
switch (cs)
{
case MONS_ZOMBIE_SMALL:
case MONS_SIMULACRUM_SMALL:
case MONS_SKELETON_SMALL:
zombie_size = Z_SMALL;
break;
case MONS_ZOMBIE_LARGE:
case MONS_SIMULACRUM_LARGE:
case MONS_SKELETON_LARGE:
zombie_size = Z_BIG;
break;
case MONS_SPECTRAL_THING:
zombie_size = -1;
break;
default:
// this should NEVER happen.
perror("\ncreate_zombie() got passed incorrect zombie type!\n");
end(0);
break;
}
// that is, random creature from which to fashion undead
if (ztype == MONS_PROGRAM_BUG)
{
// how OOD this zombie can be.
int relax = 5;
// pick an appropriate creature to make a zombie out of,
// levelwise. The old code was generating absolutely
// incredible OOD zombies.
while (true)
{
cls = _pick_random_zombie();
// on certain branches, zombie creation will fail if we use
// the mons_rarity() functions, because (for example) there
// are NO zombifiable "native" abyss creatures. Other branches
// where this is a problem are hell levels and the crypt.
// we have to watch for summoned zombies on other levels, too,
// such as the Temple, HoB, and Slime Pits.
if (you.level_type != LEVEL_DUNGEON
|| player_in_hell()
|| player_in_branch( BRANCH_HALL_OF_ZOT )
|| player_in_branch( BRANCH_VESTIBULE_OF_HELL )
|| player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
|| player_in_branch( BRANCH_CRYPT )
|| player_in_branch( BRANCH_TOMB )
|| player_in_branch( BRANCH_HALL_OF_BLADES )
|| player_in_branch( BRANCH_SNAKE_PIT )
|| player_in_branch( BRANCH_SLIME_PITS )
|| one_chance_in(1000))
{
ignore_rarity = true;
}
// don't make out-of-rarity zombies when we don't have to
if (!ignore_rarity && mons_rarity(cls) == 0)
continue;
// if skeleton, monster must have a skeleton
if ((cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
&& !mons_skeleton(cls))
{
continue;
}
// size must match, but you can make a spectral thing out
// of anything.
if (mons_zombie_size(cls) != zombie_size && zombie_size != -1)
continue;
// hack -- non-dungeon zombies are always made out of nastier
// monsters
if (you.level_type != LEVEL_DUNGEON && mons_power(cls) > 8)
break;
// check for rarity.. and OOD - identical to mons_place()
int level, diff, chance;
level = mons_level( cls ) - 4;
diff = level - power;
chance = (ignore_rarity) ? 100
: mons_rarity(cls) - (diff * diff) / 2;
if (power > level - relax && power < level + relax
&& random2avg(100, 2) <= chance)
{
break;
}
// every so often, we'll relax the OOD restrictions. Avoids
// infinite loops (if we don't do this, things like creating
// a large skeleton on level 1 may hang the game!)
if (one_chance_in(5))
relax++;
}
// set type and secondary appropriately
menv[mid].base_monster = cls;
mons_sec2 = cls;
}
else
{
menv[mid].base_monster = mons_species(ztype);
mons_sec2 = menv[mid].base_monster;
}
menv[mid].type = menv[mid].base_monster;
define_monster(mid);
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 6, 5 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac -= 2;
if (menv[mid].ac < 0)
menv[mid].ac = 0;
menv[mid].ev -= 5;
if (menv[mid].ev < 0)
menv[mid].ev = 0;
menv[mid].speed -= 2;
if (menv[mid].speed < 3)
menv[mid].speed = 3;
menv[mid].speed_increment = 70;
if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE)
{
menv[mid].type = ((mons_zombie_size(menv[mid].base_monster) == Z_BIG)
? MONS_ZOMBIE_LARGE : MONS_ZOMBIE_SMALL);
}
else if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
{
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 5, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac -= 4;
if (menv[mid].ac < 0)
menv[mid].ac = 0;
menv[mid].ev -= 2;
if (menv[mid].ev < 0)
menv[mid].ev = 0;
menv[mid].type = ((mons_zombie_size( menv[mid].base_monster ) == Z_BIG)
? MONS_SKELETON_LARGE : MONS_SKELETON_SMALL);
}
else if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE)
{
// Simulacrum aren't tough, but you can create piles of them. -- bwr
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 1, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].type = ((mons_zombie_size( menv[mid].base_monster ) == Z_BIG)
? MONS_SIMULACRUM_LARGE : MONS_SIMULACRUM_SMALL);
}
else if (cs == MONS_SPECTRAL_THING)
{
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 4, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac += 4;
menv[mid].type = MONS_SPECTRAL_THING;
}
menv[mid].base_monster = mons_sec2;
menv[mid].colour = mons_class_colour(cs);
}
mon_type = random_choose_weighted(50, MONS_ABOMINATION_SMALL,
40, MONS_ABOMINATION_LARGE,
10, MONS_TENTACLED_MONSTROSITY,
0);
mon_type = static_cast<monster_type>(
random_choose_weighted(50, MONS_ABOMINATION_SMALL,
40, MONS_ABOMINATION_LARGE,
10, MONS_TENTACLED_MONSTROSITY,
0));
int mons_place( int mon_type, beh_type behaviour, int target, bool summoned,
int px, int py, int level_type, proximity_type proximity,
int extra, int dur, bool permit_bands )
int mons_place( mgen_data mg )
// int mon_type, beh_type behaviour, int target, bool summoned,
// int px, int py, int level_type, proximity_type proximity,
// int extra, int dur, bool permit_bands )
if (you.char_direction == GDT_ASCENDING && mon_type == RANDOM_MONSTER
&& you.level_type == LEVEL_DUNGEON && !summoned)
if (you.char_direction == GDT_ASCENDING && mg.cls == RANDOM_MONSTER
&& you.level_type == LEVEL_DUNGEON && !mg.summoned())
if (mon_type == RANDOM_MONSTER
|| level_type == LEVEL_PANDEMONIUM)
{
permit_bands = true;
}
if (mg.cls == RANDOM_MONSTER || mg.level_type == LEVEL_PANDEMONIUM)
mg.flags |= MG_PERMIT_BANDS;
if (!place_monster( mid, mon_type, power, behaviour, target, summoned,
px, py, permit_bands, proximity, extra, dur ))
{
mid = place_monster(mg);
if (mid == -1)
// look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
// alert summoned being to player's presence
if (behaviour > NUM_BEHAVIOURS)
if (mg.behaviour == BEH_GOD_GIFT)
creation->flags |= MF_GOD_GIFT;
if (!(mg.flags & MG_FORCE_BEH) && player_angers_monster(creation))
creation->attitude = ATT_HOSTILE;
if (mg.behaviour == BEH_CHARMED)
if (behaviour == BEH_CHARMED)
{
creation->attitude = ATT_HOSTILE;
creation->add_ench(ENCH_CHARM);
}
// make summoned being aware of player's presence
behaviour_event(creation, ME_ALERT, MHITYOU);
}
if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
creation->add_ench(ENCH_INVIS);
int create_monster( int cls, int dur, beh_type beha, int cr_x, int cr_y,
int hitting, int zsec, bool permit_bands,
bool force_place, bool force_behaviour,
bool player_made )
int create_monster( mgen_data mg )
coord_def pos;
if (force_place && mons_class_can_pass(cls, grd[cr_x][cr_y])
&& mgrd[cr_x][cr_y] == NON_MONSTER
&& (cr_x != you.x_pos || cr_y != you.y_pos))
{
pos.x = cr_x;
pos.y = cr_y;
}
else
pos = find_newmons_square(cls, cr_x, cr_y);
if (!(mg.force_place()
&& in_bounds(mg.pos)
&& mons_class_can_pass(mg.cls, grd(mg.pos))
&& mgrd(mg.pos) == NON_MONSTER
&& mg.pos != you.pos()))
mg.pos = find_newmons_square(mg.cls, mg.pos);
if (pos.x != -1 && pos.y != -1)
{
summd = mons_place( cls, beha, hitting, true, pos.x, pos.y,
you.level_type, PROX_ANYWHERE, zsec,
dur, permit_bands );
}
if (in_bounds(mg.pos))
summd = mons_place( mg );
if (summd == -1)
{
if (see_grid( cr_x, cr_y ))
mpr("You see a puff of smoke.");
}
else
{
monsters *const creation = &menv[summd];
// dur should always be ENCH_ABJ_xx
if (dur >= 1 && dur <= 6)
creation->mark_summoned( dur, true );
// player summons do not give XP or other bonuses
// (you can still train skills on them though)
if ( player_made )
creation->flags |= MF_CREATED_FRIENDLY;
// look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
// alert summoned being to player's presence
if (beha > NUM_BEHAVIOURS)
{
if (beha == BEH_FRIENDLY || beha == BEH_GOD_GIFT)
creation->flags |= MF_CREATED_FRIENDLY;
if (beha == BEH_GOD_GIFT)
creation->flags |= MF_GOD_GIFT;
if (!force_behaviour && player_angers_monster(creation))
beha = BEH_HOSTILE;
if (beha == BEH_CHARMED)
{
creation->attitude = ATT_HOSTILE;
creation->add_ench(ENCH_CHARM);
}
// make summoned being aware of player's presence
behaviour_event(creation, ME_ALERT, MHITYOU);
}
if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
creation->add_ench(ENCH_INVIS);
}
if (summd == -1 && see_grid( mg.pos ))
mpr("You see a puff of smoke.");
{
monnumber = MONS_BLACK_DRACONIAN + random2(8);
}
while (drac_colour_incompatible(mcls, monnumber));
monbase =
static_cast<monster_type>(MONS_BLACK_DRACONIAN + random2(8));
while (drac_colour_incompatible(mcls, monbase));
: mid(id), monnum(num), genweight(gw), mlevel(ml), fix_mons(_fixmons),
generate_awake(awaken), colour(BLACK), items()
: mid(id), monbase(base), number(num), genweight(gw), mlevel(ml),
fix_mons(_fixmons), generate_awake(awaken), colour(BLACK), items()
if (create_monster( MONS_ABOMINATION_SMALL, 6, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG ) != -1)
if (create_monster(
mgen_data( MONS_ABOMINATION_SMALL, BEH_FRIENDLY, 6,
you.pos(), you.pet_target )) != -1)
if (create_monster( MONS_ABOMINATION_SMALL, 6, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU,
MONS_PROGRAM_BUG ) != -1)
if (create_monster(
mgen_data( MONS_ABOMINATION_SMALL, BEH_HOSTILE, 6,
you.pos(), MHITYOU )) != -1)
if (create_monster( beasty, 2 + random2(4), beha,
you.x_pos, you.y_pos, hitting,
MONS_PROGRAM_BUG ) != -1)
if (create_monster(
mgen_data( beasty, beha, 2 + random2(4),
you.pos(), hitting ) ) != -1)
if (defender_visible)
mpr( "The flame cauterises the wound!" );
}
else if (def->number < 19)
{
simple_monster_message( def, " grows two more!" );
def->number += 2;
heal_monster( def, 8 + random2(8), true );
if (wpn_brand == SPWPN_FLAMING)
{
if (defender_visible)
mpr( "The flame cauterises the wound!" );
}
else if (def->number < 19)
{
simple_monster_message( def, " grows two more!" );
def->number += 2;
heal_monster( def, 8 + random2(8), true );
}
// note: unique_creatures 40 + used by unique demons
if (place_monster( not_used, which_unique, level_number,
BEH_SLEEP, MHITNOT, false, 1, 1, true,
PROX_ANYWHERE, MONS_PROGRAM_BUG, 0, MMT_NO_MONS ))
if (place_monster(mg) != -1)
if (place_monster( not_used, montypes[random2(montypes.size())],
level_number, BEH_SLEEP, MHITNOT,
false, 1, 1, true, PROX_ANYWHERE,
MONS_PROGRAM_BUG, 0, MMT_NO_MONS ))
{
{
mg.cls = montypes[random2(montypes.size())];
if (place_monster(mg) != -1)
place_monster( not_used, RANDOM_MONSTER, level_number, BEH_SLEEP,
MHITNOT, false, 1, 1, true, PROX_ANYWHERE,
MONS_PROGRAM_BUG, 0, MMT_NO_MONS );
mgen_data mg;
mg.power = level_number;
mg.flags |= MG_PERMIT_BANDS;
mg.map_mask |= MMT_NO_MONS;
place_monster(mg);
mons_place( MONS_GUARDIAN_NAGA, BEH_SLEEP, MHITNOT, true,
sr.x1 + random2( sr.x2 - sr.x1 ),
sr.y1 + random2( sr.y2 - sr.y1 ) );
mons_place(
mgen_data::sleeper_at(
MONS_GUARDIAN_NAGA,
coord_def(sr.x1 + random2( sr.x2 - sr.x1 ),
sr.y1 + random2( sr.y2 - sr.y1 )) ));
mons_place( one_chance_in(7) ? MONS_KILLER_BEE_LARVA
: MONS_KILLER_BEE,
BEH_SLEEP, MHITNOT, true, x, y );
mons_place(
mgen_data::sleeper_at(
one_chance_in(7) ?
MONS_KILLER_BEE_LARVA : MONS_KILLER_BEE,
coord_def(x, y)));
int mindex = NON_MONSTER;
const bool placed
= place_monster( mindex, mid, monster_level,
m_generate_awake ? BEH_WANDER : BEH_SLEEP,
MHITNOT, true, vx, vy, false,
PROX_ANYWHERE, mspec.monnum);
mgen_data mg(static_cast<monster_type>(mid));
mg.power = monster_level;
mg.behaviour = m_generate_awake ? BEH_WANDER : BEH_SLEEP;
mg.base_type = mspec.monbase;
mg.number = mspec.number;
mg.colour = mspec.colour;
mg.pos = coord_def(vx, vy);
mon_type = ((temp_rand > 11) ? MONS_ZOMBIE_SMALL : // 50.0%
(temp_rand > 7) ? MONS_WIGHT : // 16.7%
(temp_rand > 3) ? MONS_NECROPHAGE : // 16.7%
(temp_rand > 0) ? MONS_WRAITH // 12.5%
: MONS_VAMPIRE); // 4.2%
const monster_type mon_type =
((temp_rand > 11) ? MONS_ZOMBIE_SMALL : // 50.0%
(temp_rand > 7) ? MONS_WIGHT : // 16.7%
(temp_rand > 3) ? MONS_NECROPHAGE : // 16.7%
(temp_rand > 0) ? MONS_WRAITH // 12.5%
: MONS_VAMPIRE); // 4.2%
void define_zombie( int mid, int ztype, int cs, int power )
{
int mons_sec2 = 0;
int zombie_size = 0;
bool ignore_rarity = false;
int test, cls;
if (power > 27)
power = 27;
// set size based on zombie class (cs)
switch(cs)
{
case MONS_ZOMBIE_SMALL:
case MONS_SIMULACRUM_SMALL:
case MONS_SKELETON_SMALL:
zombie_size = Z_SMALL;
break;
case MONS_ZOMBIE_LARGE:
case MONS_SIMULACRUM_LARGE:
case MONS_SKELETON_LARGE:
zombie_size = Z_BIG;
break;
case MONS_SPECTRAL_THING:
zombie_size = -1;
break;
default:
// this should NEVER happen.
perror("\ncreate_zombie() got passed incorrect zombie type!\n");
end(0);
break;
}
// that is, random creature from which to fashion undead
if (ztype == MONS_PROGRAM_BUG)
{
// how OOD this zombie can be.
int relax = 5;
// pick an appropriate creature to make a zombie out of,
// levelwise. The old code was generating absolutely
// incredible OOD zombies.
while (true)
{
// this limit can be updated if mons->number goes >8 bits..
test = random2(182); // not guaranteed to be valid, so..
cls = mons_species(test);
if (cls == MONS_PROGRAM_BUG)
continue;
// on certain branches, zombie creation will fail if we use
// the mons_rarity() functions, because (for example) there
// are NO zombifiable "native" abyss creatures. Other branches
// where this is a problem are hell levels and the crypt.
// we have to watch for summoned zombies on other levels, too,
// such as the Temple, HoB, and Slime Pits.
if (you.level_type != LEVEL_DUNGEON
|| player_in_hell()
|| player_in_branch( BRANCH_HALL_OF_ZOT )
|| player_in_branch( BRANCH_VESTIBULE_OF_HELL )
|| player_in_branch( BRANCH_ECUMENICAL_TEMPLE )
|| player_in_branch( BRANCH_CRYPT )
|| player_in_branch( BRANCH_TOMB )
|| player_in_branch( BRANCH_HALL_OF_BLADES )
|| player_in_branch( BRANCH_SNAKE_PIT )
|| player_in_branch( BRANCH_SLIME_PITS )
|| one_chance_in(1000))
{
ignore_rarity = true;
}
// don't make out-of-rarity zombies when we don't have to
if (!ignore_rarity && mons_rarity(cls) == 0)
continue;
// monster class must be zombifiable
if (!mons_zombie_size(cls))
continue;
// if skeleton, monster must have a skeleton
if ((cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
&& !mons_skeleton(cls))
{
continue;
}
// size must match, but you can make a spectral thing out of anything.
if (mons_zombie_size(cls) != zombie_size && zombie_size != -1)
continue;
// hack -- non-dungeon zombies are always made out of nastier
// monsters
if (you.level_type != LEVEL_DUNGEON && mons_power(cls) > 8)
break;
// check for rarity.. and OOD - identical to mons_place()
int level, diff, chance;
level = mons_level( cls ) - 4;
diff = level - power;
chance = (ignore_rarity) ? 100
: mons_rarity(cls) - (diff * diff) / 2;
if (power > level - relax && power < level + relax
&& random2avg(100, 2) <= chance)
{
break;
}
// every so often, we'll relax the OOD restrictions. Avoids
// infinite loops (if we don't do this, things like creating
// a large skeleton on level 1 may hang the game!)
if (one_chance_in(5))
relax++;
}
// set type and secondary appropriately
menv[mid].number = cls;
mons_sec2 = cls;
}
else
{
menv[mid].number = mons_species(ztype);
mons_sec2 = menv[mid].number;
}
menv[mid].type = menv[mid].number;
define_monster(mid);
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 6, 5 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac -= 2;
if (menv[mid].ac < 0)
menv[mid].ac = 0;
menv[mid].ev -= 5;
if (menv[mid].ev < 0)
menv[mid].ev = 0;
menv[mid].speed -= 2;
if (menv[mid].speed < 3)
menv[mid].speed = 3;
menv[mid].speed_increment = 70;
if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE)
{
menv[mid].type = ((mons_zombie_size(menv[mid].number) == Z_BIG)
? MONS_ZOMBIE_LARGE : MONS_ZOMBIE_SMALL);
}
else if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
{
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 5, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac -= 4;
if (menv[mid].ac < 0)
menv[mid].ac = 0;
menv[mid].ev -= 2;
if (menv[mid].ev < 0)
menv[mid].ev = 0;
menv[mid].type = ((mons_zombie_size( menv[mid].number ) == Z_BIG)
? MONS_SKELETON_LARGE : MONS_SKELETON_SMALL);
}
else if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE)
{
// Simulacrum aren't tough, but you can create piles of them. -- bwr
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 1, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].type = ((mons_zombie_size( menv[mid].number ) == Z_BIG)
? MONS_SIMULACRUM_LARGE : MONS_SIMULACRUM_SMALL);
}
else if (cs == MONS_SPECTRAL_THING)
{
menv[mid].hit_points = hit_points( menv[mid].hit_dice, 4, 4 );
menv[mid].max_hit_points = menv[mid].hit_points;
menv[mid].ac += 4;
menv[mid].type = MONS_SPECTRAL_THING;
}
menv[mid].number = mons_sec2;
menv[mid].colour = mons_class_colour(cs);
} // end define_zombie()
if ( create_monster(RANDOM_ELEMENT(golems), 5, BEH_FRIENDLY,
you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG) != -1 )
if (create_monster(
mgen_data( RANDOM_ELEMENT(golems),
BEH_FRIENDLY, 5, you.pos(),
you.pet_target )) != -1)
create_monster( summon_any_demon(dct), std::min(power/50,6),
BEH_FRIENDLY, you.x_pos, you.y_pos, you.pet_target,
MONS_PROGRAM_BUG );
create_monster(
mgen_data( summon_any_demon(dct), BEH_FRIENDLY,
std::min(power / 50, 6),
you.pos(), you.pet_target ));
create_monster( mon_chosen, 3,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
chosen_x, chosen_y,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG );
create_monster(
mgen_data( mon_chosen,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
3, coord_def(chosen_x, chosen_y),
MHITYOU ) );
const int mon = create_monster( MONS_DANCING_WEAPON, power_level + 3,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG, false, false, false,
true );
const int mon =
create_monster(
mgen_data( MONS_DANCING_WEAPON,
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
power_level + 3, you.pos(),
friendly ? you.pet_target : MHITYOU ));
create_monster(skeltypes[power_level], std::min(power/50,6),
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
you.x_pos, you.y_pos,
friendly ? you.pet_target : MHITYOU,
MONS_PROGRAM_BUG);
create_monster(
mgen_data(
skeltypes[power_level],
friendly ? BEH_FRIENDLY : BEH_HOSTILE,
std::min(power/50,6),
you.pos(),
friendly ? you.pet_target : MHITYOU ));
create_monster( mon, 0, BEH_SLEEP,
you.x_pos, you.y_pos, MHITNOT, MONS_PROGRAM_BUG,
true );
{
create_monster(
mgen_data::sleeper_at(
static_cast<monster_type>(mon),
you.pos()));
}
create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos,
MHITNOT, MONS_PROGRAM_BUG );
create_monster(
mgen_data::hostile_at(
static_cast<monster_type>(mtype),
you.pos() ) );
{
mons_place( RANDOM_MONSTER, BEH_HOSTILE, MHITNOT, false, 1, 1,
LEVEL_ABYSS, PROX_AWAY_FROM_PLAYER ); // PROX_ANYWHERE?
}
mons_place(mons);