1 /**********************************************************************************
2 * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3 * Copyright (c) 2010, Moloch
4 * Copyright (c) 2018, Ketmar Dark
6 * This file is part of Spelunky.
8 * You can redistribute and/or modify Spelunky, including its source code, under
9 * the terms of the Spelunky User License.
11 * Spelunky is distributed in the hope that it will be entertaining and useful,
12 * but WITHOUT WARRANTY. Please see the Spelunky User License for more details.
14 * The Spelunky User License should be available in "Game Information", which
15 * can be found in the Resource Explorer, or as an external file called COPYING.
16 * If not, please obtain a new copy of Spelunky from <http://spelunkyworld.com/>
18 **********************************************************************************/
19 // room generation for Area 2, the Mines (bizarre mode)
20 class RoomGenT0B : RoomGenT0;
22 private final string choose (string s0, string s1) {
23 return (levgen.global.randRoom(0, 1) ? s1 : s0);
26 private final string choose4 (string s0, string s1, string s2, string s3) {
27 switch (levgen.global.randRoom(0, 3)) {
37 private final string choose6 (string s0, string s1, string s2, string s3, string s4, string s5) {
38 switch (levgen.global.randRoom(0, 5)) {
51 override void generate (int rx, int ry) {
52 //string strTemp, strObs1, strObs2, strObs3;
53 //int roomPath, roomPathAbove;
55 //var tile, xpos, ypos, block;
57 GameGlobal global = levgen.global;
59 strTemp = "0000000000"~
68 int roomPath = levgen.getRPath(rx, ry); //[scrGetRoomX(x), scrGetRoomY(y)];
69 int roomPathAbove = -1;
71 if (ry != 0) roomPathAbove = levgen.getRPath(rx, ry-1); //scrGetRoomY(y-128)];
73 if (rx == levgen.startRoomX && ry == levgen.startRoomY) {
75 int n = (roomPath == 2 ? global.randRoom(5, 8) : global.randRoom(1, 4));
97 case 2: strTemp = choose("11111111112222222222000000000000000000000008000000000000000000000000001111111111",
98 "2220000000000000090L000000111P000002111L000211122L000211200002111120001111111111"); break;
99 case 3: strTemp = choose("00000000000008000000000000000000L000000000P111111000L111111000L00111111111111111",
100 "00000002200211120000002220022000000021100000000220009020000001111727201111111111"); break;
101 case 4: strTemp = choose("0000000000008000000000000000000000000L000111111P000111111L001111100L001111111111",
102 "21112222220222000000000000002000000900000200212000000021200007711111701111111111"); break;
104 case 5: strTemp = choose("60000600000000000000000000000000000000000008000000000000000000000000002021111120",
105 "111111111122222222220000000000L022200000P111110000L022210900L0000111101112022211"); break;
106 case 6: strTemp = choose("11111111112222222222000000000000000000000008000000000000000000000000002021111120",
107 "111111111122222222220000000000000002220L000011111P009012220L011110000L1122202111"); break;
108 case 7: strTemp = choose("00000000000008000000000000000000L000000000P111111000L111111000L00011111111101111",
109 "22222222220000000000000900000000111021000012002100011102111001200002101111001111"); break;
110 case 8: strTemp = choose("0000000000008000000000000000000000000L000111111P000111111L001111000L001111011111",
111 "21111221120222200220000000000000020900000001111000021122112000400004001112002111"); break;
113 } else if (rx == levgen.endRoomX && ry == levgen.endRoomY) {
115 int n = (roomPathAbove == 2 ? global.randRoom(1, 4) : global.randRoom(3, 6));
117 case 1: { strTemp = choose("00000000006000060000000000000000000000000008000000000000000000000000001111111111",
118 "00000000000000222000000211100000011112000011221100000000040001100001101120900211"); break; }
119 case 2: { strTemp = choose("00000000000000000000000000000000000000000008000000000000000000000000001111111111",
120 "00000000000000000000000100000000012000000001100100090400110021111022011111201101"); break; }
121 case 3: { strTemp = choose("00000000000010021110001001111000110111129012000000111111111021111111201111111111",
122 "00000000000000000000000000100000000210000010011000001100409010220111121011021111"); break; }
123 case 4: { strTemp = choose("00000000000111200100011110010021111011000000002109011111111102111111121111111111",
124 "00000000000220090000000011100000002120000001111100000211120000111111100021111120"); break; }
126 case 5: { strTemp = choose("60000600000000000000000000000000000000000008000000000000000000000000001111111111",
127 "11111111110000000000000800000000000000000000000000021111111001111111101111111111"); break; }
128 case 6: { strTemp = choose("11111111110222222220000000000000000000000008000000000000000000000000001111111111",
129 "11111111110211111120022222222000000000000008000000220000000022000000001111111111"); break; }
131 } else if (roomPath == 0) {
134 if (global.currLevel > 1 && !global.altar && global.randRoom(1, 12) == 1) { //rand(1,16) == 1)
137 } else if (global.idol || ry == 3) {
138 n = global.randRoom(1, 9);
140 n = global.randRoom(1, 10);
141 if (n == 10) global.idol = true;
142 // else n = rand(1,9);
147 case 1: { strTemp = choose4("00000000000010111100000000000000011010000050000000000000000000000000001111111111",
148 "00000000000010111100000000000000011010000050000000000000000000000000001111111111",
149 "00000000000210211220000000000000021012000050000000000000000000000000001111111111",
150 "00000000000222222220000000000000022020000050000000000000000000000000001111111111"); break; }
152 case 2: { strTemp = choose("110000000040L600000011P000000011L000000011L5000000110000000011000000001111111111",
153 "120600000040000000001100000000120L000000111P500000111L000000112L0000001111111111"); break; }
154 case 3: { strTemp = choose("00000000110060000L040000000P110000000L110050000L11000000001100000000111111111111",
155 "006000002100000000040000000011000000L021050000P111000000L111000000L2111111111111"); break; }
156 case 4: { strTemp = choose("110000000040L600000011P000000011L000000011L0000000110000000011000000001112222111",
157 "22200002220000000000100000000110L002200211P221120212L222220212L00000001112222211"); break; }
158 case 5: { strTemp = choose("00000000110060000L040000000P110000000L110000000L11000000001100000000111112222111",
159 "2220000222000000000010000000012002200L012021122P112022222L210000000L211122222111"); break; }
160 case 6: { strTemp = choose("11111111110221111220002111120000022220000002222000002111120002211112201111111111",
161 "11111111110112112110022011022000002200000020220200021211212001111111101111111111"); break; }
162 case 7: { strTemp = choose4("11111111111112222111112000021111102201111120000211111022011111200002111112222111",
163 "11111111111122222211120000002111022220111200000021111200211112000000211112222111",
164 "111111111111tttttt1111t0v00t1111t0000t1111t0000t1111tG$$0t1111tttttt111111111111", // these 2 are sealed treasure rooms
165 "111111111111tttttt1121t00v0t1121t0000t1221t0000t1211tG$$0t1211tttttt111111111111"); break; }
166 case 8: { strTemp = choose("11111111110000000000110000001111222222111111111111112222221122000000221100000011",
167 "11111111110002222000100000000112002200211102112011122111122120112211021000000001"); break; }
168 case 9: { strTemp = choose6("121111112100L2112L0011P1111P1111L2112L1111L1111L1111L1221L1100L0000L001111221111",
169 "121122112100L0000L0011P1111P1111L2112L1112L1111L2111L2112L1100L2112L001211111121",
170 "121111112100L2120L0011P1111P1112L0000L2112L2000L211211221P110000000L001111221111",
171 "12111111210021221200100200200110000000011100000011120211202100000000001111221111",
172 "12111111210L000000001P122221011L111111011L212212011L110011010L000000001111221111",
173 "12111111210000110000100002001112120001111020000021100021201100200020001111221111"); break; }
175 case 10: { strTemp = "22000000220000B0000000000000000000000000000000000000000000000000I000001111A01111"; break; }
177 case 11: { strTemp = "220000002200000000000000000000000000000000000000000000x0000002211112201111111111"; break; }
179 } else if (roomPath == 0 || roomPath == 1) {
181 switch (global.randRoom(1, 13)) {
183 case 1: { strTemp = "60000600000000000000000000000000000000000050000000000000000000000000001111111111"; break; }
184 case 2: { strTemp = "60000600000000000000000000000000000000005000050000000000000000000000001111111111"; break; }
185 case 3: { strTemp = choose("60000600000000000000000000000000050000000000000000000000000011111111111111111111",
186 "60000600000000000000000000000060000600000000000000000000000000000000001111111111"); break; }
187 case 4: { strTemp = choose("60000600000000000000000000000000000000000000000000000222220000111111001111111111",
188 "00000000000600000000000000000000000000000000000000002000000002200000001111111111"); break; }
189 case 5: { strTemp = "11111111112222222222000000000000000000000050000000000000000000000000001111111111"; break; }
190 case 6: { strTemp = "11111111112111111112022222222000000000000050000000000000000000000000001111111111"; break; }
192 case 7: { strTemp = choose4("11111111112111111112211111111221111111120111111110022222222000000000001111111111",
193 "11111111112111111112211112111221121011120110202210022000002000000000001111111111",
194 "11111111112111111112211111111221221211120200202110000000022000211200001111111111",
195 "11111111112111111112211112111221120022120222200020000000200002222112201111111111"); break; }
198 if (global.randRoom(1, 2) == 1) strTemp = "1111111111000000000L111111111P000000000L5000050000000000000000000000001111111111";
199 else strTemp = "1111111111L000000000P111111111L0000000005000050000000000000000000000001111111111"; break;
201 case 9: { strTemp = choose6("000000000000L0000L0000P1111P0000L0000L0000P1111P0000L1111L0000L1111L001111111111",
202 "000000000000L022200000P111100000L111110000L111110000L111111000L11111101111111111",
203 "00000000000002220L000001111P000011111L000011111L000111111L000211111L001111111111",
204 "000000000000000220000L002120000P111111000L11111200002111111000211111201111111111",
205 "0000000000000022200000002120L000011111P000211111L0011111120002111112001111111111",
206 "00000000000L000000L00P112211P00L112200L00L111111P000221111L000221111L01111111111"); break; }
208 case 10: { strTemp = choose("00000000000111111110001111110000000000005000050000000000000000000000001111111111",
209 "00000000000111111110002222220000000000000050000000000000000000000000001111111111"); break; }
210 case 11: { strTemp = choose("00000000000000000000000000000000000000000021111200021111112021111111121111111111",
211 "00000000000000000000000200200000112212000021111100011111111021111111121111111111"); break; }
213 case 12: { strTemp = choose4("2222222222000000000000000000L001111111P001050000L011000000L010000000L01111111111",
214 "222222222200000000L000222221P001111111L001050000L0110000000010000000001111111111", // new
215 "222222222200000000000L000000000P111111100L500000100L000000110L000000011111111111",
216 "22222222220L000000000P122222000L111111100L50000010000000001100000000011111111111"); break; } // new
219 switch (global.randRoom(0, 11)) {
220 case 0: strTemp = "00000000000000000000000000000000000000000NHyyyyN3003HyyyyH30333HHHH3333333333333"; break;
221 case 1: strTemp = "000000000000000002000002000000000000000003HyHHyH3003HyyyyH30333HHHH33NNN333N3N33"; break;
222 case 2: strTemp = "00000000000000000N00000N00000000000000000NHyyyyH3003HyyyyH30333HHHH3333NNN33NN33"; break;
223 case 3: strTemp = "00000000000000000000000000000000000000000NJyyyyJ100NJyyyyJ10111JJJJ1111111111111"; break;
224 case 4: strTemp = "000000000000000002000002000000000000000001JyJJyJ1001JyyyyJ10111JJJJ1111111111111"; break;
225 case 5: strTemp = "000000000000000001000001000000000000000001JyyyyJ1001JyyyyJ10111JJJJ1111111111111"; break;
226 case 6: strTemp = "00000000000000000000000000000000000000000N^wwwwN3003^wwww^30333^^^^3333333333333"; break;
227 case 7: strTemp = "000000000000000002000002000000000000000003^w^^w^3003^wwww^30333^^^^33NNN333N3N33"; break;
228 case 8: strTemp = "00000000000000000N00000N00000000000000000N^wwww^3003^wwww^30333^^^^3333NNN33NN33"; break;
229 case 9: strTemp = "00000000000000000000000000000000000000000NZwwwwZ100NZwwwwZ10111ZZZZ1111111111111"; break;
230 case 10: strTemp = "000000000000000002000002000000000000000001ZwZZwZ1001ZwwwwZ10111ZZZZ1111111111111"; break;
231 case 11: strTemp = "000000000000000001000001000000000000000001ZwwwwZ1001ZwwwwZ10111ZZZZ1111111111111"; break;
232 default: FatalError("FUCK?!");
236 } else if (roomPath == 3) {
238 switch (global.randRoom(1, 8)) {
240 case 1: { strTemp = "00000000000000000000000000000000000000000050000000000000000000000000001111111111"; break; }
241 case 2: { strTemp = "00000000000000000000000000000000000000005000050000000000000000000000001111111111"; break; }
242 case 3: { strTemp = "00000000000000000000000000000050000500000000000000000000000011111111111111111111"; break; }
243 case 4: { strTemp = choose("00000000000000000000000600000000000000000000000000000111110000111111001111111111",
244 "00000000000000000000020600002000000000000000000000000211120000111111001111111111"); break; }
246 case 5: { strTemp = choose("00000000000111111110001111110000000000005000050000000000000000000000001111111111",
247 "00000000000211111120002222220000000000005000050000000000000000000000001111111111"); break; }
248 case 6: { strTemp = choose("00000000000000000000000000000000000000000021111200021111112021111111121111111111",
249 "00000000000000000000000022000000021120000021111200021111112021111111121111111111"); break; }
250 case 7: { strTemp = choose("10000000011112002111111200211100000000000022222000111111111111111111111111111111",
251 "10000000011112002111111100111100220022000000000000110000001111222222111111111111"); break; }
253 case 8: { strTemp = choose4("0000000000000000000000000000L001111111P001050000L011000000L010000000L01111111111",
254 "000000000000022000L000211221P001111111L001050000L0110000000010000000001111111111", // new
255 "000000000000000000000L000000000P111111100L500000100L000000110L000000011111111111",
256 "00000000000L000220000P122112000L111111100L50000010000000001100000000011111111111"); break; // new
259 } else if (roomPath == 4) {
261 strTemp = "111111111111111111111111221111111l000211...000W010...00000k0..Kiiii000bbbbbbbbbb";
262 int n = global.randRoom(1, 7);
264 if (global.scumGenShopType > 0) n = global.scumGenShopType;
266 case 1: shopType = 'General'; break;
267 case 2: shopType = 'Bomb'; break;
268 case 3: shopType = 'Weapon'; break;
269 case 4: shopType = 'Rare'; break;
270 case 5: shopType = 'Clothing'; break;
271 case 6: shopType = 'Craps'; strTemp = "11111111111111111111111122111111Kl000211..bQ00W010.0+00000k0.q+dd00000bbbbbbbbbb"; break;
272 case 7: shopType = 'Kissing'; strTemp = "111111111111111111111111221111111l000211...000W010...00000k0..K00D0000bbbbbbbbbb"; global.damsel = true; break;
274 } else if (roomPath == 5) {
276 strTemp = "111111111111111111111111221111112000l11101W0000...0k00000...000iiiiK..bbbbbbbbbb";
277 int n = global.randRoom(1, 7);
279 if (global.scumGenShopType > 0) n = global.scumGenShopType;
281 case 1: shopType = 'General'; break;
282 case 2: shopType = 'Bomb'; break;
283 case 3: shopType = 'Weapon'; break;
284 case 4: shopType = 'Rare'; break;
285 case 5: shopType = 'Clothing'; break;
286 case 6: shopType = 'Craps'; strTemp = "111111111111111111111111221111112000lK1101W0Q00b..0k00000+0.00000dd+q.bbbbbbbbbb"; break;
287 case 7: shopType = 'Kissing'; strTemp = "111111111111111111111111221111112000l11101W0000...0k00000...0000D00K..bbbbbbbbbb"; global.damsel = true; break;
289 } else if (roomPath == 8) {
291 strTemp = "111000011111s0000s11111200211111s0000s11111200211111s0000s11111200211111s0000s11";
292 } else if (roomPath == 9) {
294 strTemp = "111000011111s0000s1111100001111100S0001111S0110S11111STTS1111111M111111111111111";
298 if (roomPath == 7) n = global.randRoom(4, 12); // top of pit
299 else if (roomPathAbove != 2) n = global.randRoom(1, 12); // any
300 else n = global.randRoom(1, 8); // need open ceiling
302 case 1: { strTemp = choose("00000000006000060000000000000000000000006000060000000000000000000000000000000000",
303 "00000000000060000000000000000000000000000000600000000000000000000000000000000000"); break; }
304 case 2: { strTemp = choose("00000000006000060000000000000000000000000000050000000000000000000000001202111111",
305 "00000000000000000000022202220000000000000000250000020200000000000000001202111111"); break; }
306 case 3: { strTemp = choose("00000000006000060000000000000000000000005000000000000000000000000000001111112021",
307 "00000000000002220000000000022000000000005000020000000000022000000000001111112021"); break; }
308 case 4: { strTemp = choose("00000000006000060000000000000000000000000000000000000000000002200002201112002111",
309 "00000000000000000000002222220000110011000000000000002000020002120021201111001111"); break; }
310 case 5: { strTemp = choose("00000000000000220000000000000000200002000112002110011100111012000000211111001111",
311 "00000000000021111200000000000000200002000212002120011100111011000000111112001111"); break; }
312 case 6: { strTemp = choose("00000000000060000000000000000000000000000000000000001112220002100000001110111111",
313 "00000000000022000000000002220000010111000001000000001112220002100000001110211111"); break; }
314 case 7: { strTemp = choose("00000000000060000000000000000000000000000000000000002221110000000001201111110111",
315 "00000000000000002200002220000000111010000000001000002221110000000001201111120111"); break; }
316 case 8: { strTemp = choose("00000000000060000000000000000000000000000000000000002022020000100001001111001111",
317 "00000000000002002000000100100000110011000012002100011100111001200002101111001111"); break; }
318 case 9: { strTemp = choose("11111111112222222222000000000000000000000000000000000000000000000000001120000211",
319 "11111111112111111112021111112000211112000002222000000000000002000000201120000211"); break; }
320 case 10: { strTemp = choose("11111111112222111111000002211100000002110000000000200000000000000000211120000211",
321 "11111111110111111111021111111100212111110002021110000000200002000000111120000111"); break; }
322 case 11: { strTemp = choose("11111111111111112222111220000011200000000000000000000000000012000000001120000211",
323 "11111111111111111110111111112011111221000111200200000200000012000000201120000211"); break; }
324 case 12: { strTemp = choose("11111111112111111112021111112000211112000002112000000022000002200002201111001111",
325 "11111111112112222112012000021001002200100102112110000000000002200002201111001111"); break; }
330 foreach (int i; 0..80) {
333 string strObs1 = "00000";
334 string strObs2 = "00000";
335 string strObs3 = "00000";
336 int tile = strTemp[i];
338 //if (tile == "8") { strObs1 = "00000"; strObs2 = "00000"; strObs3 = "00900" }
342 switch (global.randRoom(1, 12)) {
343 case 1: { strObs1 = "00900"; strObs2 = "01110"; strObs3 = "11111"; break; }
344 case 2: { strObs1 = "00900"; strObs2 = "02120"; strObs3 = "02120"; break; }
345 case 3: { strObs1 = "00000"; strObs2 = "00000"; strObs3 = "92222"; break; }
346 case 4: { strObs1 = "00000"; strObs2 = "00000"; strObs3 = "22229"; break; }
347 case 5: { strObs1 = "00000"; strObs2 = "11001"; strObs3 = "19001"; break; }
348 case 6: { strObs1 = "00000"; strObs2 = "10011"; strObs3 = "10091"; break; }
349 case 7: { strObs1 = "11111"; strObs2 = "10001"; strObs3 = "40094"; break; }
350 case 8: { strObs1 = "00000"; strObs2 = "12021"; strObs3 = "12921"; break; }
351 case 9: { strObs1 = "00900"; strObs2 = "03330"; strObs3 = "33333"; break; }
352 case 10: { strObs1 = "00000"; strObs2 = "33003"; strObs3 = "39003"; break; }
353 case 11: { strObs1 = "00000"; strObs2 = "N00N3"; strObs3 = "N0093"; break; }
354 case 12: { strObs1 = "N3333"; strObs2 = "30003"; strObs3 = "40094"; break; }
356 } else if (tile == "5") {
358 switch (global.randRoom(1, 19)) {
359 case 1: { strObs1 = "11111"; strObs2 = "00000"; strObs3 = "00000"; break; }
360 case 2: { strObs1 = "00000"; strObs2 = "11110"; strObs3 = "00000"; break; }
361 case 3: { strObs1 = "00000"; strObs2 = "01111"; strObs3 = "00000"; break; }
362 case 4: { strObs1 = "00000"; strObs2 = "00000"; strObs3 = "11111"; break; }
363 case 5: { strObs1 = "00000"; strObs2 = "20200"; strObs3 = "17177"; break; }
364 case 6: { strObs1 = "00000"; strObs2 = "02020"; strObs3 = "71717"; break; }
365 case 7: { strObs1 = "00000"; strObs2 = "00202"; strObs3 = "77171"; break; }
366 case 8: { strObs1 = "00000"; strObs2 = "22200"; strObs3 = "11100"; break; }
367 case 9: { strObs1 = "00000"; strObs2 = "02220"; strObs3 = "01110"; break; }
368 case 10: { strObs1 = "00000"; strObs2 = "00222"; strObs3 = "00111"; break; }
369 case 11: { strObs1 = "11100"; strObs2 = "22200"; strObs3 = "00000"; break; }
370 case 12: { strObs1 = "01110"; strObs2 = "02220"; strObs3 = "00000"; break; }
371 case 13: { strObs1 = "00111"; strObs2 = "00222"; strObs3 = "00000"; break; }
372 case 14: { strObs1 = "00000"; strObs2 = "02220"; strObs3 = "21112"; break; }
373 case 15: { strObs1 = "00000"; strObs2 = "20100"; strObs3 = "77117"; break; }
374 case 16: { strObs1 = "00000"; strObs2 = "00102"; strObs3 = "71177"; break; }
375 case 17: { strObs1 = "NN3NN"; strObs2 = "00000"; strObs3 = "00000"; break; }
376 case 18: { strObs1 = "00000"; strObs2 = "N33N0"; strObs3 = "00000"; break; }
377 case 19: { strObs1 = "00000"; strObs2 = "0N33N"; strObs3 = "00000"; break; }
379 } else if (tile == "6") {
381 switch (global.randRoom(1, 12)) {
382 case 1: { strObs1 = "11111"; strObs2 = "00000"; strObs3 = "00000"; break; }
383 case 2: { strObs1 = "22222"; strObs2 = "00000"; strObs3 = "00000"; break; }
384 case 3: { strObs1 = "11100"; strObs2 = "22200"; strObs3 = "00000"; break; }
385 case 4: { strObs1 = "01110"; strObs2 = "02220"; strObs3 = "00000"; break; }
386 case 5: { strObs1 = "00111"; strObs2 = "00222"; strObs3 = "00000"; break; }
387 case 6: { strObs1 = "00000"; strObs2 = "01110"; strObs3 = "00000"; break; }
388 case 7: { strObs1 = "00000"; strObs2 = "01110"; strObs3 = "02220"; break; }
389 case 8: { strObs1 = "00000"; strObs2 = "02220"; strObs3 = "01110"; break; }
390 case 9: { strObs1 = "00000"; strObs2 = "00220"; strObs3 = "01111"; break; }
391 case 10: { strObs1 = "00000"; strObs2 = "22200"; strObs3 = "11100"; break; }
392 case 11: { strObs1 = "NNNNN"; strObs2 = "00000"; strObs3 = "00000"; break; }
393 case 12: { strObs1 = "00000"; strObs2 = "0NNN0"; strObs3 = "00000"; break; }
397 if (tile == "5" || tile == "6" || tile == "8") {
398 //strTemp = string_delete(strTemp, j, 5);
399 //strTemp = string_insert(strObs1, strTemp, j);
400 strTemp[j..j+5] = strObs1;
402 //strTemp = string_delete(strTemp, j, 5);
403 //strTemp = string_insert(strObs2, strTemp, j);
404 strTemp[j..j+5] = strObs2;
406 //strTemp = string_delete(strTemp, j, 5);
407 //strTemp = string_insert(strObs3, strTemp, j);
408 strTemp[j..j+5] = strObs3;
414 transient array!int bzprobs;
416 // used by scrEntityGenBizarre to avoid creating a bunch more global variables
417 // called by scrEntityGenMix
418 // higher number = less chance of enemy spawning
419 int bizGetProbBase (name aname) {
420 auto global = levgen.global;
421 // defaults (area 1 - mines)
423 case 'spearTrap': return 80;
424 case 'giantSpider': return 50;
425 case 'bat': return 80;
426 case 'spider': return 90;
427 case 'ufo': return 350;
428 case 'springTrap': return 80;
429 case 'snake': return 70;
430 case 'caveman': return 110;
431 case 'manTrap': return 270;
432 case 'hawkman': return 400;
433 case 'frog': return 300;
434 case 'yeti': return 300;
435 case 'fireFrog': return 350;
436 case 'zombie': return 270;
437 case 'vampire': return 950;
438 case 'alien': return 400;
439 case 'monkey': return 320;
440 case 'outlaw': return 9000; // disabled in levelgen
441 case 'magmaMan': return 1200;
442 case 'tombLord': return 90;
443 case 'yetiKing': return 80;
444 case 'alienBoss': return 120;
445 case 'smashTrap': return 480;
446 case 'thwompTrap': return 200;
447 case 'arrowTrap': return 4;
448 case 'arrowTrap2': return 40;
449 case 'monkeyVine': return 20;
450 case 'fish': return 30;
451 case 'blob': return 300; // slime
452 case 'greenFrog': return 460;
453 case 'cobra': return 300;
454 case 'greenSpider': return 440;
455 case 'man': return 400;
456 case 'floater': return 520; //700
459 if (global.levelType == 1) {
460 // area 2 - lush jungle
461 if (global.cemetary) {
463 case 'zombie': return 800;
464 case 'vampire': return 1000;
468 case 'bat': return 70;
469 case 'spider': return 90;
470 case 'snake': return 80;
471 case 'frog': return 40;
472 case 'manTrap': return 70;
473 case 'vampire': return 420;
474 case 'ufo': return 340;
475 case 'spearTrap': return 15;
476 case 'fireFrog': return 150;
477 case 'smashTrap': return 290;
478 case 'thwompTrap': return 110;
479 case 'yetiKing': return 70;
480 case 'alienBoss': return 90;
482 } else if (global.levelType == 2) {
483 // area 3 - ice caves
484 if (!global.yetiLair && aname == 'ufo') return 30;
486 case 'snake': return 200;
487 case 'bat': return 140;
488 case 'spider': return 150;
489 case 'springTrap': return 10;
490 case 'fireFrog': return 360;
491 case 'manTrap': return 320;
492 case 'yeti': return 25;
493 case 'smashTrap': return 200;
494 case 'thwompTrap': return 70;
495 case 'tombLord': return 60;
496 case 'yetiKing': return 20;
497 case 'alienBoss': return 30;
498 case 'cobra': return 400;
499 case 'blob': return 240;
501 } else if (global.levelType == 3) {
504 case 'snake': return 80;
505 case 'bat': return 80;
506 case 'spider': return 100;
507 case 'caveman': return 60;
508 case 'hawkman': return 60;
509 case 'yeti': return 300;
510 case 'vampire': return 600;
511 case 'fireFrog': return 300;
512 case 'spearTrap': return 12;
513 case 'smashTrap': return 70;
514 case 'thwompTrap': return 40;
515 case 'magmaMan': return 1600;
516 case 'tombLord': return 40;
517 case 'yetiKing': return 70;
518 case 'alienBoss': return 80;
519 case 'cobra': return 180;
520 case 'blob': return 290;
521 case 'floater': return 480;
522 case 'man': return 150;
529 int bizGetProb (name aname) {
530 if (!aname) return 0;
532 int aid = NameToIIndex(aname);
533 if (aid > 0 && aid < bzprobs.length && bzprobs[aid] >= 0) return bzprobs[aid];
535 auto global = levgen.global;
537 auto res = bizGetProbBase(aname);
539 if (global.genGiantSpider) {
540 if (aname == 'spider') res = round(res/2.0);
541 if (aname == 'greenSpider') res = round(res/2.0);
543 if (global.genYetiKing && aname == 'yeti') res = round(res/2.0);
544 if (global.genAlienBoss) {
545 if (aname == 'alien') res = round(res/2.0);
546 if (aname == 'ufo') res = round(res/2.0);
548 if (global.genTombLord) {
549 if (aname == 'zombie') res = round(res/2.0);
550 if (aname == 'cobra') res = round(res/2.0);
551 if (aname == 'hawkman') res = round(res/2.0);
553 if (global.cemetary && aname == 'zombie') res = round(res/2);
555 // entity quantity variations
557 float d = global.randRoom(4, 6)/2.0;
558 if (aname == 'springTrap' && global.randRoom(1, c) == 1) res = round(res/d);
559 else if (aname == 'spearTrap' && global.randRoom(1, c) == 1) res = round(res/d);
560 else if (aname == 'smashTrap' && global.randRoom(1, c) == 1) res = round(res/d);
561 else if (aname == 'thwompTrap' && global.randRoom(1, c) == 1) res = round(res/d);
562 else if (aname == 'fireFrog' && global.randRoom(1, c) == 1) res = round(res/d);
563 else if (aname == 'magmaMan' && global.randRoom(1, c) == 1) res = round(res/d);
564 else if (aname == 'yeti' && !global.genYetiKing && global.randRoom(1, c) == 1) res = round(res/d);
565 else if ((aname == 'ufo' || aname == 'alien') && !global.genAlienBoss && global.randRoom(1, c) == 1) {
566 if (aname == 'ufo') res = round(res/d);
567 if (aname == 'alien') res = round(res/d);
569 else if (aname == 'blob' && global.randRoom(1, c) == 1) res = round(res/d);
570 else if (aname == 'floater' && global.randRoom(1, c) == 1) res = round(res/d);
571 else if (aname == 'man' && global.randRoom(1, c) == 1) res = round(res/d);
572 else if (aname == 'monkey' && global.randRoom(1, c) == 1) res = round(res/d);
573 else if (aname == 'frog' && global.randRoom(1, c) == 1) res = round(res/d);
574 else if (aname == 'greenFrog' && global.randRoom(1, c) == 1) res = round(res/d);
575 else if (aname == 'hawkman' && !global.genTombLord && global.randRoom(1, c) == 1) res = round(res/d);
576 else if (aname == 'cobra' && !global.genTombLord && global.randRoom(1, c) == 1) res = round(res/d);
578 while (bzprobs.length <= aid) bzprobs[$] = -1;
585 override void genEntityAt (int tileX, int tileY) {
586 auto global = levgen.global;
587 auto level = levgen.level;
589 if (level.isInShop(tileX, tileY) || tileY == 0) return;
591 MapTile t = level.getTileAt(tileX, tileY);
593 int x = tileX*16, y = tileY*16;
595 if ((!t || (!t.altar && !t.tree)) &&
597 !level.checkTilesInRect(x, y-32, 16, 32) &&
598 !level.isEnemyInRect(x, y-16, 16, 16) &&
599 !level.isLavaAtPoint(x, y-16) &&
600 (!level.isSolidAtPoint(x-16, y) || !level.isSolidAtPoint(x+16, y)) &&
601 level.isSolidAtPoint(x, y+16) &&
602 //!!!!level.isSolidAtPoint(x, y, oXMarket) &&
603 level.calcNearestEnterDist(x, y) > 64)
605 if (global.levelType == 1 && global.darkLevel && !level.isLiquidAtPoint(x, y-32) && global.randRoom(1, 20) == 1) {
606 level.MakeMapObject(x, y-32, 'oTikiTorch');
607 } else if (global.randRoom(1, trunc(ceil(float(bizGetProb('spearTrap'))/global.trapMult))) == 1 &&
608 x != 160 && x != 176 && x != 320 && x != 336 && x != 480 && x != 496 &&
609 (!t || (!t.invincible && t.objName != 'Xoc Block')))
611 auto sol = level.isSolidAtPoint(x, y-16);
612 bool doCreate = true;
613 if (global.levelType != 1 && global.levelType != 3) {
614 doCreate = !level.checkTilesInRect(x-16, y-32, 48, 32);
619 wet = sol.water || sol.wet;
620 sol.cleanDeath = true;
621 sol.instanceRemove();
624 (level.isLiquidAtPoint(x-2, y) || level.isLiquidAtPoint(x+18, y) ||
625 level.isLiquidAtPoint(x-2, y-16) || level.isLiquidAtPoint(x+18, y-16)))
629 auto trap = level.MakeMapTile(tileX, tileY, 'oSpearTrapBottom');
631 trap = level.MakeMapTile(tileX, tileY-1, (global.darkLevel ? 'oSpearTrapLit' : 'oSpearTrapTop'));
633 //if (wet) writeln("generated WET spear trap");
643 if (y > 32 && !level.isSolidAtPoint(x, y-16) && global.genGoldEntrance && !global.madeGoldEntrance) {
644 if (global.randRoom(1, global.goldChance) == 1) {
646 instance_create(x, y-16, oGoldDoor);
648 global.madeGoldEntrance = true;
651 global.goldChance -= 1;
655 if (t && t.isInstanceAlive && !t.altar) {
656 if (global.cemetary) level.scrTreasureGenBizarre(x, y, 10); else level.scrTreasureGenBizarre(x, y);
661 level.tileXY2roomXY(tileX, tileY-1, roomX, roomY); //k8: why -1?
664 if (roomX == level.startRoomX && roomY == level.startRoomY) return;
666 if (tileY < GameLevel::NormalTilesHeight-4 &&
667 !level.checkTilesInRect(tileX*16, (tileY+1)*16, 17, 33, &level.cbCollisionAnySolidOrLiquid) &&
668 !level.isObjectAtPoint(tileX*16+8, (tileY+1)*16+8, &level.cbIsObjectEnemy))
670 if (global.genGiantSpider && !global.giantSpider &&
671 global.randRoom(1, trunc(ceil(40.0/global.config.enemyMult))) == 1 &&
672 !level.checkTilesInRect((tileX+1)*16, (tileY+1)*16, 17, 33, &level.cbCollisionAnySolid/*k8:???OrLiquid*/))
674 level.MakeMapObject(tileX*16, (tileY+1)*16, 'oGiantSpiderHang');
675 //!!!if (global.hasStickyBombs and rand(1, 2) == 1) { obj.pasteless = true; obj.carries = "Crate"; }
676 if (global.enemyMult >= 2 && global.randRoom(1, trunc(ceil(200.0/global.config.eMult))) == 1) global.giantSpider = false;
677 else global.giantSpider = true;
679 else if (global.darkLevel && global.randRoom(1, 60) == 1) level.MakeMapTile(tileX, tileY+1, 'oLamp');
680 else if (global.darkLevel && global.randRoom(1, 40) == 1) level.MakeMapObject(tileX*16, (tileY+1)*16, 'oScarab');
681 else if (global.randRoom(1, trunc(ceil(float(bizGetProb('floater'))/global.eMult))) == 1) {
682 auto obj = level.MakeMapObject(x, y+16, 'oFloater');
685 switch (rand(1, 6)) {
687 case 5: obj.carries = "Big Sapphire"; break;
688 case 6: obj.carries = "Big Ruby"; break;
689 default: obj.carries = "Big Emerald";
691 if (rand(1, 20-global.currLevel) == 1) { obj.explosive = true; obj.sprite_index = sFloaterEvil; }
695 else if (global.randRoom(1, trunc(ceil(float(bizGetProb('bat'))/global.eMult))) == 1) level.MakeMapObject(x, y+16, 'oBat');
696 else if (global.randRoom(1, trunc(ceil(float(bizGetProb('spider'))/global.eMult))) == 1 && !level.isLadderAtPoint(x+8, y+24)) level.MakeMapObject(x, y+16, 'oSpiderHang');
697 else if (global.randRoom(1, trunc(ceil(float(bizGetProb('greenSpider'))/global.eMult))) == 1 && !level.isLadderAtPoint(x+8, y+24)) level.MakeMapObject(x, y+16, 'oGreenSpiderHang');
698 else if (y > 16 && tileY < GameLevel::NormalTilesHeight-3 && !level.isSolidAtPoint(x, y-16)) {
699 if (global.randRoom(1, trunc(ceil(float(bizGetProb('ufo'))/global.eMult))) == 1) level.MakeMapObject(x, y-16, 'oUFO');
707 rgLevelType = 0; // not ready yet