black market fixes
[k8vacspelynky.git] / packages / Generator / RoomGenT1.vc
blobba006da3ea1bc0c3eeb64ec129ed5eda88fc5914
1 /**********************************************************************************
2  * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3  * Copyright (c) 2010, Moloch
4  * Copyright (c) 2018, Ketmar Dark
5  *
6  * This file is part of Spelunky.
7  *
8  * You can redistribute and/or modify Spelunky, including its source code, under
9  * the terms of the Spelunky User License.
10  *
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.
13  *
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/>
17  *
18  **********************************************************************************/
19 // room generation for Area 2, the Lush Jungle
20 class RoomGenT1 : RoomGen;
23 void generateBlackMarket (int rx, int ry) {
24   GameGlobal global = levgen.global;
26   strTemp = "0000000000"~
27             "0000000000"~
28             "0000000000"~
29             "0000000000"~
30             "0000000000"~
31             "0000000000"~
32             "0000000000"~
33             "0000000000";
35   int roomPath = levgen.getRPath(rx, ry); //[scrGetRoomX(x), scrGetRoomY(y)];
36   int roomPathAbove = -1;
37   shopType = 'General';
38   if (ry != 0) roomPathAbove = levgen.getRPath(rx, ry-1); //scrGetRoomY(y-128)];
40   if (rx == levgen.startRoomX && ry == levgen.startRoomY) {
41     // starting room
42     int n = (roomPath == 2 ? global.randRoom(3, 4) : global.randRoom(1, 2));
43     switch (n) {
44       case 1: { strTemp = "6000060000"~
45                           "0000000000"~
46                           "0000000000"~
47                           "0000000000"~
48                           "0008000000"~
49                           "0000000000"~
50                           "0000000000"~
51                           "1111111111";
52                           break; }
53       case 2: { strTemp = "1111111111"~
54                           "2222222222"~
55                           "0000000000"~
56                           "0000000000"~
57                           "0008000000"~
58                           "0000000000"~
59                           "0000000000"~
60                           "1111111111";
61                           break; }
62       // hole
63       case 3: { strTemp = "6000060000"~
64                           "0000000000"~
65                           "0000000000"~
66                           "0000000000"~
67                           "0008000000"~
68                           "0000000000"~
69                           "0000000000"~
70                           "2021111120";
71                           break; }
72       case 4: { strTemp = "1111111111"~
73                           "2222222222"~
74                           "0000000000"~
75                           "0000000000"~
76                           "0008000000"~
77                           "0000000000"~
78                           "0000000000"~
79                           "2021111120";
80                           break; }
81       default: FatalError("000");
82     }
83   } else if (rx == levgen.endRoomX && ry == levgen.endRoomY) {
84     // exit room
85     int n = (roomPathAbove == 2 ? global.randRoom(1, 2) : global.randRoom(3, 4));
86     switch (n) {
87       case 1: { strTemp = "0000000000"~
88                           "0000000000"~
89                           "0000000000"~
90                           "0000000000"~
91                           "0008000000"~
92                           "0000000000"~
93                           "0000000000"~
94                           "1111111111";
95                           break; }
96       case 2: { strTemp = "0000000000"~
97                           "6000060000"~
98                           "0000000000"~
99                           "0000000000"~
100                           "0008000000"~
101                           "0000000000"~
102                           "0000000000"~
103                           "1111111111";
104                           break; }
105       case 3: { strTemp = "6000060000"~
106                           "0000000000"~
107                           "0000000000"~
108                           "0000000000"~
109                           "0008000000"~
110                           "0000000000"~
111                           "0000000000"~
112                           "1111111111";
113                           break; }
114       case 4: { strTemp = "1111111111"~
115                           "2222222222"~
116                           "0000000000"~
117                           "0000000000"~
118                           "0008000000"~
119                           "0000000000"~
120                           "0000000000"~
121                           "1111111111";
122                           break; }
123       default: FatalError("001");
124     }
125   } else if (roomPath == 1) {
126     switch (global.randRoom(1, 8)) {
127       // basic rooms
128       case 1: { strTemp = "6000060000"~
129                           "0000000000"~
130                           "0000000000"~
131                           "0000000000"~
132                           "0050000000"~
133                           "0000000000"~
134                           "0000000000"~
135                           "1111111111";
136                           break; }
137       case 2: { strTemp = "6000060000"~
138                           "0000000000"~
139                           "0000000000"~
140                           "0000000000"~
141                           "5000050000"~
142                           "0000000000"~
143                           "0000000000"~
144                           "1111111111";
145                           break; }
146       case 3: { strTemp = "6000060000"~
147                           "0000000000"~
148                           "0000000000"~
149                           "5000050000"~
150                           "0000000000"~
151                           "0000000000"~
152                           "1111111111"~
153                           "1111111111";
154                           break; }
155       case 4: { strTemp = "6000060000"~
156                           "0000000000"~
157                           "0000000000"~
158                           "0000000000"~
159                           "0000000000"~
160                           "0001111100"~
161                           "0011111100"~
162                           "1111111111";
163                           break; }
164       // spikes
165       case 5: { strTemp = "1111111111"~
166                           "V0000V0000"~
167                           "0000000000"~
168                           "0000000000"~
169                           "0000000000"~
170                           "1000000001"~
171                           "1ssssssss1"~
172                           "1111111111";
173                           break; }
174       // upper plats
175       case 6: { strTemp = "0000000000"~
176                           "0000000000"~
177                           "0000000000"~
178                           "0000000000"~
179                           "5000050000"~
180                           "0000000000"~
181                           "0000000000"~
182                           "1111111111";
183                           break; }
184       // water
185       case 7: { strTemp = "0000000000"~
186                           "0000000000"~
187                           "0000000000"~
188                           "013wwww310"~
189                           "013wwww310"~
190                           "113wwww311"~
191                           "1113333111"~
192                           "1111111111";
193                           break; }
194       case 8: { strTemp = "0060000000"~
195                           "0000000000"~
196                           "0000000000"~
197                           "0000000000"~
198                           "013wwww310"~
199                           "113wwww311"~
200                           "1113333111"~
201                           "1111111111";
202                           break; }
203       default: FatalError("002");
204     }
205   } else if (roomPath == 3) {
206     // main room
207     switch (global.randRoom(1, 7)) {
208       // basic rooms
209       case 1: { strTemp = "0000000000"~
210                           "0000000000"~
211                           "0000000000"~
212                           "0000000000"~
213                           "0050000000"~
214                           "0000000000"~
215                           "0000000000"~
216                           "1111111111";
217                           break; }
218       case 2: { strTemp = "0000000000"~
219                           "0000000000"~
220                           "0000000000"~
221                           "0000000000"~
222                           "5000050000"~
223                           "0000000000"~
224                           "0000000000"~
225                           "1111111111";
226                           break; }
227       case 3: { strTemp = "0000000000"~
228                           "0000000000"~
229                           "0000000000"~
230                           "5000050000"~
231                           "0000000000"~
232                           "0000000000"~
233                           "1111111111"~
234                           "1111111111";
235                           break; }
237       // upper plats
238       case 4: { strTemp = "0000000000"~
239                           "0000000000"~
240                           "0000000000"~
241                           "0000000000"~
242                           "0002222220"~
243                           "0011111110"~
244                           "1111111111"~
245                           "1111111111";
246                           break; }
247       case 5: { strTemp = "0000000000"~
248                           "0000000000"~
249                           "0000000000"~
250                           "0000000000"~
251                           "0000000221"~
252                           "0000022111"~
253                           "0000221111"~
254                           "1111111111";
255                           break; }
256       // water
257       case 6: { strTemp = "0000000000"~
258                           "0000000000"~
259                           "0000000000"~
260                           "013wwww310"~
261                           "013wwww310"~
262                           "113wwww311"~
263                           "1113333111"~
264                           "1111111111";
265                           break; }
266       case 7: { strTemp = "0000000000"~
267                           "0060000000"~
268                           "0000000000"~
269                           "0000000000"~
270                           "013wwww310"~
271                           "113wwww311"~
272                           "1113333111"~
273                           "1111111111";
274                           break; }
275       default: FatalError("003");
276     }
277   } else if (roomPath == LevelGen::RType.Shop4 && rx == 3/*496*/) {
278     // ankh shop
279     strTemp = "0000000011"~
280               ".....b0AlK"~
281               "......bbbb"~
282               ".........."~
283               "1111111111"~
284               "1111111111"~
285               "1111111111"~
286               "1111111111";
287     shopType = 'Ankh';
288     writeln("*** generated Ankh shop");
289   } else if (roomPath == LevelGen::RType.Shop4) {
290     // shop
291     strTemp = ".........."~
292               ".........."~
293               "....22...."~
294               "..2l00l2.."~
295               "0.000000.0"~
296               "0k000000k0"~
297               "000iiiiK00"~
298               "bbbbbbbbbb";
300     shopType = '';
302     int n = global.randRoom(1, 5);
303     int m = n;
305     while (!shopType) {
306            if (n == 1) { if (!global.genSupplyShop) { shopType = 'General'; global.genSupplyShop = true; } }
307       else if (n == 2) { if (!global.genBombShop) { shopType = 'Bomb'; global.genBombShop = true; } }
308       else if (n == 3) { if (!global.genWeaponShop) { shopType = 'Weapon'; global.genWeaponShop = true; } }
309       else if (n == 4) { if (!global.genRareShop) { shopType = 'Rare'; global.genRareShop = true; } }
310       else if (n == 5) { if (!global.genClothingShop) { shopType = 'Clothing'; global.genClothingShop = true; } }
311       ++n;
312       if (n > 5) n = 1;
313       if (n == m) {
314         shopType = 'General';
315         break;
316       }
317     }
318   } else if (roomPath == LevelGen::RType.Shop5) {
319     // craps
320     strTemp = "1111111111"~
321               "1111111111"~
322               "1111221111"~
323               "112000lK11"~
324               "01W0Q00b.."~
325               "0k00000+0."~
326               "00000zz+q."~
327               "bbbbbbbbbb";
328     shopType = 'Craps';
329   } else {
330     // drop
331     int n = (roomPathAbove != 2 ? global.randRoom(1, 6) : global.randRoom(1, 5));
332     switch (n) {
333       case 1: { strTemp = "00G0000000"~
334                           "00H1111000"~
335                           "00G2222000"~
336                           "00G0000000"~
337                           "00G0000000"~
338                           "00G0000022"~
339                           "0000000211"~
340                           "1111202111";
341                           break; }
342       case 2: { strTemp = "0000000G00"~
343                           "0001111H00"~
344                           "0002222G00"~
345                           "0000000G00"~
346                           "0000000G00"~
347                           "2200000G00"~
348                           "112T000000"~
349                           "1111202111";
350                           break; }
351       case 3: { strTemp = "00000000G0"~
352                           "60000011H0"~
353                           "00000000G0"~
354                           "00000000G0"~
355                           "G0000000G0"~
356                           "H1122000G0"~
357                           "G0000000G0"~
358                           "11100001H1";
359                           break; }
360       case 4: { strTemp = "0000000G00"~
361                           "0001111H00"~
362                           "0002222G00"~
363                           "0000000G00"~
364                           "0000000G00"~
365                           "0000000000"~
366                           "2000022222"~
367                           "1000111111";
368                           break; }
369       case 5: { strTemp = "00G0000000"~
370                           "00H1111000"~
371                           "00G2222000"~
372                           "00G0000000"~
373                           "00G0000000"~
374                           "0000000000"~
375                           "2222200002"~
376                           "1111110001";
377                           break; }
378       //
379       case 6: { strTemp = "1111111111"~
380                           "1111111111"~
381                           "1200000021"~
382                           "2000000002"~
383                           "0000000000"~
384                           "0220000220"~
385                           "2112002112"~
386                           "1111001111";
387                           break; }
388       default: FatalError("007");
389     }
390   }
392   if (strTemp.length != 80) FatalError("ooops");
394   // add obstacles
395   foreach (int i; 0..80) {
396     int j = i;
398     string strObs1 = "00000";
399     string strObs2 = "00000";
400     string strObs3 = "00000";
401     string strObs4 = "00000";
402     int tile = strTemp[i];
404     if (tile == "8") {
405       strObs1 = "00900";
406       strObs2 = "01110";
407       strObs3 = "11111";
408     } else if (tile == "5") {
409       // ground
410       int n = (global.randRoom(1, 8) == 1 ? global.randRoom(100, 102) : global.randRoom(1, 2));
411       switch (n) {
412         case 1: { strObs1 = "00000";
413                   strObs2 = "00000";
414                   strObs3 = "22222";
415                   break; }
416         case 2: { strObs1 = "00000";
417                   strObs2 = "22222";
418                   strObs3 = "11111";
419                   break; }
420         case 100: { strObs1 = "00000";
421                     strObs2 = "00000";
422                     strObs3 = "0T022";
423                     break; }
424         case 101: { strObs1 = "00000";
425                     strObs2 = "00000";
426                     strObs3 = "20T02";
427                     break; }
428         case 102: { strObs1 = "00000";
429                     strObs2 = "00000";
430                     strObs3 = "220T0";
431                     break; }
432         default: FatalError("009");
433       }
434     } else if (tile == "6") {
435       // air
436       switch (global.randRoom(1, 4)) {
437         case 1: { strObs1 = "11112";
438                   strObs2 = "22220";
439                   strObs3 = "00000";
440                   break; }
441         case 2: { strObs1 = "21111";
442                   strObs2 = "02222";
443                   strObs3 = "00000";
444                   break; }
445         case 3: { strObs1 = "22222";
446                   strObs2 = "00000";
447                   strObs3 = "00000";
448                   break; }
449         case 4: { strObs1 = "11111";
450                   strObs2 = "21112";
451                   strObs3 = "02120";
452                   break; }
453         default: FatalError("00a");
454       }
455     } else if (tile == "V") {
456       // vines
457       switch (global.randRoom(1, 3)) {
458         case 1: { strObs1 = "L0L0L";
459                   strObs2 = "L0L0L";
460                   strObs3 = "L000L";
461                   strObs4 = "L0000";
462                   break; }
463         case 2: { strObs1 = "L0L0L";
464                   strObs2 = "L0L0L";
465                   strObs3 = "L000L";
466                   strObs4 = "0000L";
467                   break; }
468         case 3: { strObs1 = "0L0L0";
469                   strObs2 = "0L0L0";
470                   strObs3 = "0L0L0";
471                   strObs4 = "000L0";
472                   break; }
473         default: FatalError("00a");
474       }
475     }
477     if (tile == "5" || tile == "6" || tile == "8" || tile == "V") {
478       //strTemp = string_delete(strTemp, j, 5);
479       //strTemp = string_insert(strObs1, strTemp, j);
480       strTemp[j..j+5] = strObs1;
481       j += 10;
482       //strTemp = string_delete(strTemp, j, 5);
483       //strTemp = string_insert(strObs2, strTemp, j);
484       strTemp[j..j+5] = strObs2;
485       j += 10;
486       //strTemp = string_delete(strTemp, j, 5);
487       //strTemp = string_insert(strObs3, strTemp, j);
488       strTemp[j..j+5] = strObs3;
489     }
490     if (tile == "V") {
491       j += 10;
492       //strTemp = string_delete(strTemp, j, 5);
493       //strTemp = string_insert(strObs4, strTemp, j);
494       strTemp[j..j+5] = strObs4;
495     }
496   }
500 override void generate (int rx, int ry) {
501   GameGlobal global = levgen.global;
503   if (global.blackMarket) {
504     generateBlackMarket(rx, ry);
505     return;
506   }
508   strTemp = "0000000000"~
509             "0000000000"~
510             "0000000000"~
511             "0000000000"~
512             "0000000000"~
513             "0000000000"~
514             "0000000000"~
515             "0000000000";
517   int roomPath = levgen.getRPath(rx, ry); //[scrGetRoomX(x), scrGetRoomY(y)];
518   int roomPathAbove = -1;
519   shopType = 'General';
520   if (ry != 0) roomPathAbove = levgen.getRPath(rx, ry-1); //scrGetRoomY(y-128)];
522   if (rx == levgen.startRoomX && ry == levgen.startRoomY) {
523     // starting room
524     int n = (roomPath == 2 ? global.randRoom(3, 4) : global.randRoom(1, 2));
525     switch (n) {
526       case 1: { strTemp = "6000060000"~
527                           "0000000000"~
528                           "0000000000"~
529                           "0000000000"~
530                           "0008000000"~
531                           "0000000000"~
532                           "0000000000"~
533                           "1111111111";
534                           break; }
535       case 2: { strTemp = "1111111111"~
536                           "2222222222"~
537                           "0000000000"~
538                           "0000000000"~
539                           "0008000000"~
540                           "0000000000"~
541                           "0000000000"~
542                           "1111111111";
543                           break; }
544       // hole
545       case 3: { strTemp = "6000060000"~
546                           "0000000000"~
547                           "0000000000"~
548                           "0000000000"~
549                           "0008000000"~
550                           "0000000000"~
551                           "0000000000"~
552                           "2021111120";
553                           break; }
554       case 4: { strTemp = "1111111111"~
555                           "2222222222"~
556                           "0000000000"~
557                           "0000000000"~
558                           "0008000000"~
559                           "0000000000"~
560                           "0000000000"~
561                           "2021111120";
562                           break; }
563       default: FatalError("000");
564     }
565   } else if (rx == levgen.endRoomX && ry == levgen.endRoomY) {
566     // exit room
567     int n = (global.lake == 1 ? 5 : roomPathAbove == 2 ? global.randRoom(1, 4) : global.randRoom(3, 4));
568     switch (n) {
569       case 1: { strTemp = "0000000000"~
570                           "0000000000"~
571                           "0000000000"~
572                           "0000000000"~
573                           "0008000000"~
574                           "0000000000"~
575                           "0000000000"~
576                           "1111111111";
577                           break; }
578       case 2: { strTemp = "0000000000"~
579                           "0011111100"~
580                           "0000000000"~
581                           "0000000000"~
582                           "0008000000"~
583                           "0000000000"~
584                           "0000000000"~
585                           "1111111111";
586                           break; }
587       case 3: { strTemp = "6000060000"~
588                           "0000000000"~
589                           "0000000000"~
590                           "0000000000"~
591                           "0008000000"~
592                           "0000000000"~
593                           "0000000000"~
594                           "1111111111";
595                           break; }
596       case 4: { strTemp = "1111111111"~
597                           "2222222222"~
598                           "0000000000"~
599                           "0000000000"~
600                           "0008000000"~
601                           "0000000000"~
602                           "0000000000"~
603                           "1111111111";
604                           break; }
605       case 5: { strTemp = "0000000000"~
606                           "0000090000"~
607                           "0221111220"~
608                           "wwvvvvvvww"~
609                           "wwwwwwwwww"~
610                           "wwwwwwwwww"~
611                           "wwwwwwwwww"~
612                           "wwwwwwwwww";
613                           break; }
614       default: FatalError("001");
615     }
616   } else if (roomPath == 0 && global.randRoom(1, 3) <= 2) {
617     // side room
618     int n;
619     if (!global.altar && global.randRoom(1, 12) == 1) {
620       n = 10;
621       global.altar = true;
622     } else if (global.idol) {
623       n = global.randRoom(1, 8);
624     } else {
625       n = global.randRoom(1, 9);
626       if (n == 9) global.idol = true;
627     }
629     switch (n) {
630       // upper plats
631       case 1: { strTemp = "0000000000"~
632                           "0010111100"~
633                           "0000000000"~
634                           "0001101000"~
635                           "0050000000"~
636                           "0000000000"~
637                           "0000000000"~
638                           "1111111111";
639                           break; }
640       case 2: { strTemp = "1111111111"~
641                           "11V0000211"~
642                           "1200000211"~
643                           "0000000211"~
644                           "0000000211"~
645                           "1120000211"~
646                           "1112002111"~
647                           "1111001111";
648                           break; }
649       case 3: { strTemp = "1111111111"~
650                           "112V000011"~
651                           "1120000021"~
652                           "1120000000"~
653                           "1120000000"~
654                           "1120000211"~
655                           "1112002111"~
656                           "1111001111";
657                           break; }
658       case 4: { strTemp = "1112002111"~
659                           "1100000222"~
660                           "1200000211"~
661                           "0000000222"~
662                           "0000000211"~
663                           "1120000222"~
664                           "11177T7111"~
665                           "1111111111";
666                           break; }
667       case 5: { strTemp = "1112002111"~
668                           "2220000011"~
669                           "1120000021"~
670                           "2220000000"~
671                           "1120000000"~
672                           "2220000211"~
673                           "1117T77111"~
674                           "1111111111";
675                           break; }
676       case 6: { strTemp = "1112002111"~
677                           "2220000011"~
678                           "1120000021"~
679                           "2220000000"~
680                           "1120000000"~
681                           "2220000211"~
682                           "1117T77111"~
683                           "1111111111";
684                           break; }
685       // water rooms
686       case 7: { strTemp = "0000000000"~
687                           "11wwwwww11"~
688                           "11wwwwww11"~
689                           "113wwww311"~
690                           "113wwww311"~
691                           "113wwww311"~
692                           "1113333111"~
693                           "1111111111";
694                           break; }
695       case 8: { strTemp = "0000000000"~
696                           "0000rr0000"~
697                           "000rttr000"~
698                           "00rrrrrr00"~
699                           "00V0000000"~
700                           "0000000000"~
701                           "0000000000"~
702                           "0000000000";
703                           break; }
704       // idols
705       case 9:
706       {
707           if (global.cemetary) strTemp = "tttttttttt"~
708                                          "tttttttttt"~
709                                          "ttp0C00ptt"~
710                                          "ttt0tt0ttt"~
711                                          "4000000004"~
712                                          "ttt0tt0ttt"~
713                                          "ttp0000ptt"~
714                                          "1111111111";
715           else strTemp = "0100000010"~
716                          "0000I00000"~
717                          "01BBBBBB10"~
718                          "1100000011"~
719                          "11wwwwww11"~
720                          "11wwwwww11"~
721                          "113wwww311"~
722                          "1111111111";
723           break;
724       }
725       // altars
726       case 10: { strTemp = "2200000022"~
727                            "0000000000"~
728                            "0000000000"~
729                            "0000000000"~
730                            "0000000000"~
731                            "0000x00000"~
732                            "0221111220"~
733                            "1111111111";
734                            break; }
735       default: FatalError("002");
736     }
737   } else if (roomPath == 0 || roomPath == 1) {
738     // main room
739     switch (global.randRoom(1, 10)) {
740       // basic rooms
741       case 1: { strTemp = "6000060000"~
742                           "0000000000"~
743                           "0000000000"~
744                           "0000000000"~
745                           "0050000000"~
746                           "0000000000"~
747                           "0000000000"~
748                           "1111111111";
749                           break; }
750       case 2: { strTemp = "6000060000"~
751                           "0000000000"~
752                           "0000000000"~
753                           "0000000000"~
754                           "5000050000"~
755                           "0000000000"~
756                           "0000000000"~
757                           "1111111111";
758                           break; }
759       case 3: { strTemp = "6000060000"~
760                           "0000000000"~
761                           "0000000000"~
762                           "5000050000"~
763                           "0000000000"~
764                           "0000000000"~
765                           "1111111111"~
766                           "1111111111";
767                           break; }
768       case 4: { strTemp = "6000060000"~
769                           "0000000000"~
770                           "0000000000"~
771                           "0000000000"~
772                           "0000000000"~
773                           "0001111100"~
774                           "0011111100"~
775                           "1111111111";
776                           break; }
777       case 5: { strTemp = "2222222222"~
778                           "0000000000"~
779                           "0000000000"~
780                           "0000tt0000"~
781                           "00r0220r00"~
782                           "00t0tt0t00"~
783                           "0rtrttrtr0"~
784                           "1111111111";
785                           break; }
786       case 6: {
787           if (global.randRoom(1,2) == 1) strTemp = "0L00000000"~
788                                                   "1L11111111"~
789                                                   "0L22222220"~
790                                                   "0L00000000"~
791                                                   "0002002000"~
792                                                   "0111221110"~
793                                                   "1120000211"~
794                                                   "1111111111";
795           else strTemp = "00000000L0"~
796                          "11111111L1"~
797                          "02222222L0"~
798                          "00000000L0"~
799                          "0002002000"~
800                          "0111221110"~
801                          "1120000211"~
802                          "1111111111";
803           break;
804       }
805       // spikes
806       case 7: { strTemp = "1111111111"~
807                           "V0000V0000"~
808                           "0000000000"~
809                           "0000000000"~
810                           "0000000000"~
811                           "1000000001"~
812                           "1ssssssss1"~
813                           "1111111111";
814                           break; }
815       // upper plats
816       case 8: { strTemp = "0000000000"~
817                           "0000000000"~
818                           "0000000000"~
819                           "0000000000"~
820                           "5000050000"~
821                           "0000000000"~
822                           "0000000000"~
823                           "1111111111";
824                           break; }
825       // water
826       case 9: { strTemp = "0000000000"~
827                           "0000000000"~
828                           "0000000000"~
829                           "013wwww310"~
830                           "013wwww310"~
831                           "113wwww311"~
832                           "1113333111"~
833                           "1111111111";
834                           break; }
835       case 10: { strTemp = "0060000000"~
836                            "0000000000"~
837                            "0000000000"~
838                            "0000000000"~
839                            "013wwww310"~
840                            "113wwww311"~
841                            "1113333111"~
842                            "1111111111";
843                            break; }
844       default: FatalError("003");
845     }
846   } else if (roomPath == 3) {
847     // main room
848     switch (global.randRoom(1, 7)) {
849       // basic rooms
850       case 1: { strTemp = "0000000000"~
851                           "0000000000"~
852                           "0000000000"~
853                           "0000000000"~
854                           "0050000000"~
855                           "0000000000"~
856                           "0000000000"~
857                           "1111111111";
858                           break; }
859       case 2: { strTemp = "0000000000"~
860                           "0000000000"~
861                           "0000000000"~
862                           "0000000000"~
863                           "5000050000"~
864                           "0000000000"~
865                           "0000000000"~
866                           "1111111111";
867                           break; }
868       case 3: { strTemp = "0000000000"~
869                           "0000000000"~
870                           "0000000000"~
871                           "5000050000"~
872                           "0000000000"~
873                           "0000000000"~
874                           "1111111111"~
875                           "1111111111";
876                           break; }
878       // upper plats
879       case 4: { strTemp = "0000000000"~
880                           "0000000000"~
881                           "0000000000"~
882                           "0000000000"~
883                           "0002222220"~
884                           "0011111110"~
885                           "1111111111"~
886                           "1111111111";
887                           break; }
888       case 5: { strTemp = "0000000000"~
889                           "0000000000"~
890                           "0000000000"~
891                           "0000000000"~
892                           "0000000221"~
893                           "0000022111"~
894                           "0000221111"~
895                           "1111111111";
896                           break; }
897       // water
898       case 6: { strTemp = "0000000000"~
899                           "0000000000"~
900                           "0000000000"~
901                           "013wwww310"~
902                           "013wwww310"~
903                           "113wwww311"~
904                           "1113333111"~
905                           "1111111111";
906                           break; }
907       case 7: { strTemp = "0000000000"~
908                           "0060000000"~
909                           "0000000000"~
910                           "0000000000"~
911                           "013wwww310"~
912                           "113wwww311"~
913                           "1113333111"~
914                           "1111111111";
915                           break; }
916       default: FatalError("004");
917     }
918   } else if (roomPath == LevelGen::RType.Shop4) {
919     // shop
920     strTemp = "1111111111"~
921               "1111111111"~
922               "1111221111"~
923               "111l000211"~
924               "...000W010"~
925               "...00000k0"~
926               "..Kiiii000"~
927               "bbbbbbbbbb";
928     int n = global.randRoom(1, 7);
929     if (global.scumGenShopType > 0) n = global.scumGenShopType;
930     switch (n) {
931       case 1: shopType = 'General'; break;
932       case 2: shopType = 'Bomb'; break;
933       case 3: shopType = 'Weapon'; break;
934       case 4: shopType = 'Rare'; break;
935       case 5: shopType = 'Clothing'; break;
936       case 6: shopType = 'Craps';
937         strTemp = "1111111111"~
938                   "1111111111"~
939                   "1111221111"~
940                   "11Kl000211"~
941                   "..bQ00W010"~
942                   ".0+00000k0"~
943                   ".q+uu00000"~
944                   "bbbbbbbbbb";
945         break;
946       case 7: shopType = 'Kissing';
947         strTemp = "1111111111"~
948                   "1111111111"~
949                   "1111221111"~
950                   "111l000211"~
951                   "...000W010"~
952                   "...00000k0"~
953                   "..K00D0000"~
954                   "bbbbbbbbbb";
955         /*oGame*/global.damsel = true;
956         break;
957       default: FatalError("005");
958     }
959   } else if (roomPath == LevelGen::RType.Shop5) {
960     // shop
961     strTemp = "1111111111"~
962               "1111111111"~
963               "1111221111"~
964               "112000l111"~
965               "01W0000..."~
966               "0k00000..."~
967               "000iiiiK.."~
968               "bbbbbbbbbb";
969     int n = global.randRoom(1, 7);
970     if (global.scumGenShopType > 0) n = global.scumGenShopType;
971     switch (n) {
972       case 1: shopType = 'General'; break;
973       case 2: shopType = 'Bomb'; break;
974       case 3: shopType = 'Weapon'; break;
975       case 4: shopType = 'Rare'; break;
976       case 5: shopType = 'Clothing'; break;
977       case 6: shopType = 'Craps';
978         strTemp = "1111111111"~
979                   "1111111111"~
980                   "1111221111"~
981                   "112000lK11"~
982                   "01W0Q00b.."~
983                   "0k00000+0."~
984                   "00000uu+q."~
985                   "bbbbbbbbbb";
986         break;
987       case 7: shopType = 'Kissing';
988         strTemp = "1111111111"~
989                   "1111111111"~
990                   "1111221111"~
991                   "112000l111"~
992                   "01W0000..."~
993                   "0k00000..."~
994                   "0000D00K.."~
995                   "bbbbbbbbbb";
996         /*oGame*/global.damsel = true;
997         break;
998       default: FatalError("006");
999     }
1000   } else if (roomPath == 7) {
1001     // Lake Bottom
1002     switch (global.randRoom(1, 8)) {
1003       case 1: { strTemp = "wwwwwwwwww"~
1004                           "wwwwwwwwww"~
1005                           "wwwwwwwwww"~
1006                           "wwwwwwwwww"~
1007                           "wwwwwwwwww"~
1008                           "wwwwwwwwww"~
1009                           "wwwwwwwwww"~
1010                           "wwwwwwwwww";
1011                           break; }
1012       case 2: { strTemp = "wwwwwwwwww"~
1013                           "wwwwwwwwww"~
1014                           "wwwwwwwwww"~
1015                           "wwwwwwwwww"~
1016                           "wwwwwwwwww"~
1017                           "wwwwwwwwww"~
1018                           "wwwwwwwwww"~
1019                           ",,,,,,,,,,";
1020                           break; }
1021       case 3: { strTemp = "wwwwwwwwww"~
1022                           "wwwwwwwwww"~
1023                           "wwwwwwwwww"~
1024                           "wwwwwwwwww"~
1025                           ",,wwwwww,,"~
1026                           "wwwwwwwwww"~
1027                           "wwwwwwwwww"~
1028                           ",,,,,,,,,,";
1029                           break; }
1030       case 4: { strTemp = "wwwwwwwwww"~
1031                           "wwwwwwwwww"~
1032                           "wwwwwwwwww"~
1033                           "wwwwwwwwww"~
1034                           ",v,wwwwwww"~
1035                           "wwv,wwwwww"~
1036                           "w,v,wwwwww"~
1037                           ",,v,,,,,ww";
1038                           break; }
1039       case 5: { strTemp = "wwwwwwwwww"~
1040                           "wwwwwwwwww"~
1041                           "wwwwwwwwww"~
1042                           "wwwwwwwwww"~
1043                           "wwwwwww,v,"~
1044                           "wwwwww,vww"~
1045                           "wwwwww,v,w"~
1046                           "w,,,,,,v,,";
1047                           break; }
1048       case 6: { strTemp = "wwwwwwwwww"~
1049                           "wwwwwwwwww"~
1050                           "wwwwwwwwww"~
1051                           "wwww,,wwww"~
1052                           "www,vv,www"~
1053                           "www,vv,www"~
1054                           "ww,,vv,,ww"~
1055                           ",,,vvvv,,,";
1056                           break; }
1057       case 7: { strTemp = "wwwwwwwwww"~
1058                           "wwwwwwwwww"~
1059                           "wwwwwwwwww"~
1060                           "www,,,,www"~
1061                           "ww,vvvv,ww"~
1062                           "w,v,w,vv,w"~
1063                           "w,wwww,vv,"~
1064                           ",,,,,,,,,,";
1065                           break; }
1066       case 8: { strTemp = "wwwwwwwwww"~
1067                           "wwwwwwwwww"~
1068                           "wwwwwwwwww"~
1069                           "www,,,,www"~
1070                           "ww,vvvv,ww"~
1071                           "w,vv,w,v,w"~
1072                           ",vv,wwww,w"~
1073                           ",,,,,,,,,,";
1074                           break; }
1075     }
1076   } else if (roomPath == 8) {
1077     // Lake Top
1078     int n = (roomPathAbove == 2 ? global.randRoom(1, 5) : global.randRoom(1, 8));
1079     switch (n) {
1080       case 1: { strTemp = "0000000000"~
1081                           "0000000000"~
1082                           "0001111000"~
1083                           "w,,vvvv,,w"~
1084                           "wwww,,wwww"~
1085                           "wwwwwwwwww"~
1086                           "wwwwwwwwww"~
1087                           "wwwwwwwwww";
1088                           break; }
1089       case 2: { strTemp = "0000000000"~
1090                           "0000000000"~
1091                           "1200000000"~
1092                           "vvwwwwwwww"~
1093                           ",wwwwwwwww"~
1094                           "wwwwwwwwww"~
1095                           "wwwwwwwwww"~
1096                           "wwwwwwwwww";
1097                           break; }
1098       case 3: { strTemp = "0000000000"~
1099                           "0000000000"~
1100                           "0000000021"~
1101                           "wwwwwwwwvv"~
1102                           "wwwwwwwww,"~
1103                           "wwwwwwwwww"~
1104                           "wwwwwwwwww"~
1105                           "wwwwwwwwww";
1106                           break; }
1107       case 4: { strTemp = "0000000000"~
1108                           "0000000000"~
1109                           "0000000000"~
1110                           "wwwwwwwwww"~
1111                           "wwwwwwwwww"~
1112                           "wwwwwwwwww"~
1113                           "wwwwwwwwww"~
1114                           "wwwwwwwwww";
1115                           break; }
1116       case 5: { strTemp = "0000000000"~
1117                           "0000000000"~
1118                           "0001111000"~
1119                           "w,,vvvv,,w"~
1120                           "www,vv,www"~
1121                           "wwwwvvwwww"~
1122                           "wwww,,wwww"~
1123                           "wwwwwwwwww";
1124                           break; }
1125       case 6: { strTemp = "0000220000"~
1126                           "0002112000"~
1127                           "0001111000"~
1128                           "w,,vvvv,,w"~
1129                           "www,vv,www"~
1130                           "wwwwvvwwww"~
1131                           "wwww,,wwww"~
1132                           "wwwwwwwwww";
1133                           break; }
1134       case 7: { strTemp = "6000060000"~
1135                           "0000000000"~
1136                           "0000000000"~
1137                           "wwwvvvvwww"~
1138                           "wwww,,wwww"~
1139                           "wwwwwwwwww"~
1140                           "wwwwwwwwww"~
1141                           "wwwwwwwwww";
1142                           break; }
1143       case 8: { strTemp = "0000220000"~
1144                           "0002112000"~
1145                           "0221111220"~
1146                           "www,,,,www"~
1147                           "wwwwwwwwww"~
1148                           "wwwwwwwwww"~
1149                           "wwwwwwwwww"~
1150                           "wwwwwwwwww";
1151                           break; }
1152     }
1153   } else if (roomPath == 9) {
1154     // Mega Mouth
1155     strTemp = "wwwwwwwwww"~
1156               "wwwwwwwwww"~
1157               "wwwwwwwwww"~
1158               "wwwwwwwwww"~
1159               "wwwJwwwwww"~
1160               "wwwwwwwwww"~
1161               "wwwwwwwwww"~
1162               ",,,,,,,,,,";
1163   } else {
1164     // drop
1165     int n = (roomPathAbove != 2 ? global.randRoom(1, 6) : global.randRoom(1, 5));
1166     switch (n) {
1167       case 1: { strTemp = "0000000000"~
1168                           "0000000000"~
1169                           "0000000000"~
1170                           "0000000000"~
1171                           "0000000000"~
1172                           "0000000022"~
1173                           "0000000211"~
1174                           "1111202111";
1175                           break; }
1176       case 2: { strTemp = "0000000000"~
1177                           "0000000000"~
1178                           "0000000000"~
1179                           "0000000000"~
1180                           "0000000000"~
1181                           "2200000000"~
1182                           "112T000000"~
1183                           "1111202111";
1184                           break; }
1185       case 3: { strTemp = "0000000000"~
1186                           "6000000000"~
1187                           "0000000000"~
1188                           "0000000000"~
1189                           "0000000000"~
1190                           "0000000000"~
1191                           "0000000000"~
1192                           "1000000001";
1193                           break; }
1194       case 4: { strTemp = "0000000000"~
1195                           "0000000000"~
1196                           "0000000000"~
1197                           "0000000000"~
1198                           "0000000000"~
1199                           "0000000000"~
1200                           "2000022222"~
1201                           "1000111111";
1202                           break; }
1203       case 5: { strTemp = "0000000000"~
1204                           "0000000000"~
1205                           "0000000000"~
1206                           "0000000000"~
1207                           "0000000000"~
1208                           "0000000000"~
1209                           "2222200002"~
1210                           "1111110001";
1211                           break; }
1212       //
1213       case 6: { strTemp = "1111111111"~
1214                           "1111111111"~
1215                           "1200000021"~
1216                           "0000000000"~
1217                           "0000000000"~
1218                           "0220000220"~
1219                           "2112002112"~
1220                           "1111001111";
1221                           break; }
1222       default: FatalError("007");
1223     }
1224   }
1226   if (strTemp.length != 80) FatalError("ooops");
1228   // add obstacles
1229   foreach (int i; 0..80) {
1230     int j = i;
1232     string strObs1 = "00000";
1233     string strObs2 = "00000";
1234     string strObs3 = "00000";
1235     string strObs4 = "00000";
1236     int tile = strTemp[i];
1238     if (tile == "8") {
1239       strObs1 = "00900";
1240       strObs2 = "01110";
1241       strObs3 = "11111";
1242     } else if (tile == "5") {
1243       // ground
1244       int n = (global.randRoom(1, 8) == 1 ? global.randRoom(100, 102) : global.randRoom(1, 2));
1245       switch (n) {
1246         case 1: { strObs1 = "00000";
1247                   strObs2 = "00000";
1248                   strObs3 = "22222";
1249                   break; }
1250         case 2: { strObs1 = "00000";
1251                   strObs2 = "22222";
1252                   strObs3 = "11111";
1253                   break; }
1254         case 100: { strObs1 = "00000";
1255                     strObs2 = "00000";
1256                     strObs3 = "0T022";
1257                     break; }
1258         case 101: { strObs1 = "00000";
1259                     strObs2 = "00000";
1260                     strObs3 = "20T02";
1261                     break; }
1262         case 102: { strObs1 = "00000";
1263                     strObs2 = "00000";
1264                     strObs3 = "220T0";
1265                     break; }
1266         default: FatalError("009");
1267       }
1268     } else if (tile == "6") {
1269       // air
1270       switch (global.randRoom(1, 4)) {
1271         case 1: { strObs1 = "11112";
1272                   strObs2 = "22220";
1273                   strObs3 = "00000";
1274                   break; }
1275         case 2: { strObs1 = "21111";
1276                   strObs2 = "02222";
1277                   strObs3 = "00000";
1278                   break; }
1279         case 3: { strObs1 = "22222";
1280                   strObs2 = "00000";
1281                   strObs3 = "00000";
1282                   break; }
1283         case 4: { strObs1 = "11111";
1284                   strObs2 = "21112";
1285                   strObs3 = "00000";
1286                   break; }
1287         default: FatalError("00a");
1288       }
1289     } else if (tile == "V") {
1290       // vines
1291       switch (global.randRoom(1, 3)) {
1292         case 1: { strObs1 = "L0L0L";
1293                   strObs2 = "L0L0L";
1294                   strObs3 = "L000L";
1295                   strObs4 = "L0000";
1296                   break; }
1297         case 2: { strObs1 = "L0L0L";
1298                   strObs2 = "L0L0L";
1299                   strObs3 = "L000L";
1300                   strObs4 = "0000L";
1301                   break; }
1302         case 3: { strObs1 = "0L0L0";
1303                   strObs2 = "0L0L0";
1304                   strObs3 = "0L0L0";
1305                   strObs4 = "000L0";
1306                   break; }
1307         default: FatalError("00a");
1308       }
1309     }
1311     if (tile == "5" || tile == "6" || tile == "8" || tile == "V") {
1312       //strTemp = string_delete(strTemp, j, 5);
1313       //strTemp = string_insert(strObs1, strTemp, j);
1314       strTemp[j..j+5] = strObs1;
1315       j += 10;
1316       //strTemp = string_delete(strTemp, j, 5);
1317       //strTemp = string_insert(strObs2, strTemp, j);
1318       strTemp[j..j+5] = strObs2;
1319       j += 10;
1320       //strTemp = string_delete(strTemp, j, 5);
1321       //strTemp = string_insert(strObs3, strTemp, j);
1322       strTemp[j..j+5] = strObs3;
1323     }
1324     if (tile == "V") {
1325       j += 10;
1326       //strTemp = string_delete(strTemp, j, 5);
1327       //strTemp = string_insert(strObs4, strTemp, j);
1328       strTemp[j..j+5] = strObs4;
1329     }
1330   }
1334 override void genTileAt (int tileX, int tileY) {
1335   name shopType = levgen.roomShopType(tileX, tileY);
1336   //if (shopType && shopType != 'General') writeln("::: ", shopType, " :::");
1338   auto global = levgen.global;
1339   auto level = levgen.level;
1341   // border tiles (moved to LevelGen)
1342   if (tileX == 0 || tileY == 0 || tileX == level.tilesWidth-1 || tileY == level.tilesHeight-1) {
1343     /+
1344     MapTile tile;
1345     // Great Lake is bottomless (nope)
1346     if (false /*global.lake && tileY == level.tilesHeight-1*/) {
1347       tile = level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1348     } else {
1349       tile = level.MakeMapTile(tileX, tileY, 'oEdgeBrick');
1350       tile.setSprite('sLush');
1351       tile.invincible = true;
1352       tile.border = true;
1353     }
1354     tile.ore = 0;
1355     //tile.treasure = '';
1356     +/
1357     level.MakeMapTile(tileX, tileY, 'oLush');
1358     return;
1359   }
1361   int roomX, roomY;
1362   level.tileXY2roomXY(tileX, tileY, roomX, roomY);
1363   level.setTileTypeAt(tileX, tileY, levgen.getRPath(roomX, roomY));
1365   auto tile = levgen.roomGetXYTileType(tileX, tileY);
1367   if (tile == "0") return;
1369   if (tile == "1") {
1370     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1371     level.MakeMapTile(tileX, tileY, 'oLush');
1372     return;
1373   }
1375   if (tile == "2") {
1376     if (global.randRoom(1, 2) != 1) return;
1377     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1378     level.MakeMapTile(tileX, tileY, 'oLush');
1379     return;
1380   }
1382   if (tile == "t") {
1383     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1384     level.MakeMapTile(tileX, tileY, 'oTemple');
1385     return;
1386   }
1388   if (tile == "r") {
1389     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1390     level.MakeMapTile(tileX, tileY, (global.randRoom(1, 2) == 1 ? 'oTemple' : 'oLush'));
1391     return;
1392   }
1394   if (tile == "3") {
1395     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1396     level.MakeMapTile(tileX, tileY, (global.randRoom(1, 2) == 1 ? 'oWaterSwim' : 'oLush'));
1397     return;
1398   }
1400   if (tile == "L") {
1401     level.MakeMapTile(tileX, tileY, 'oVine');
1402     return;
1403   }
1405   if (tile == "P") {
1406     level.MakeMapTile(tileX, tileY, 'oVineTop');
1407     return;
1408   }
1410   if (tile == "G") {
1411     level.MakeMapTile(tileX, tileY, 'oLadderOrange');
1412     return;
1413   }
1415   if (tile == "H") {
1416     level.MakeMapTile(tileX, tileY, 'oLadderTop');
1417     return;
1418   }
1420   if (tile == "7") {
1421     if (global.randRoom(1, trunc(ceil(3.0/global.config.trapMult))) == 1) {
1422       level.MakeMapTile(tileX, tileY, level.scrGenSpikeType());
1423     }
1424     return;
1425   }
1427   if (tile == "s") {
1428     level.MakeMapTile(tileX, tileY, level.scrGenSpikeType());
1429     return;
1430   }
1432   if (tile == "4") {
1433     level.MakeMapTile(tileX, tileY, 'oPushBlock');
1434     return;
1435   }
1437   if (tile == "9") {
1438     auto block = level.MakeMapTile(tileX, tileY+1, 'oLush');
1439     if (roomX == levgen.startRoomX && roomY == levgen.startRoomY) {
1440       level.MakeMapTile(tileX, tileY, 'oEntrance');
1441       level.spawnPlayerAt(tileX*16+8, tileY*16+8);
1442     } else {
1443       level.MakeMapTile(tileX, tileY, 'oExit');
1444       block.invincible = true;
1445       block.ore = 0;
1446     }
1447     return;
1448   }
1450   if (tile == "c") {
1451     level.scrLevGenCreateChest(tileX*16+8, tileY*16+8);
1452     return;
1453   }
1455   if (tile == "d") {
1456     level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1457     level.scrLevGenCreateChest(tileX*16+8, tileY*16+8);
1458     return;
1459   }
1461   if (tile == "w") {
1462     level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1463     return;
1464   }
1466   if (tile == "A") {
1467     auto obj = level.MakeMapObject(tileX*16+7, tileY*16+8, 'oAnkh');
1468     if (obj) {
1469       obj.forSale = true;
1470       obj.shopType = 'Ankh';
1471     }
1472     return;
1473   }
1475   if (tile == "z") {
1476     auto die = level.MakeMapObject(tileX*16+8, tileY*16+8, 'oDice');
1477     if (die) {
1478       die.forSale = true;
1479       die.shopType = 'Craps';
1480     }
1481     return;
1482   }
1484   if (tile == "v") {
1485     // k8: it looks like a brick in the water; dunno why it is done this way
1486     //     it seems that water brick is created to mark it as "water"
1487     //k8:???level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1488     level.MakeMapTile(tileX, tileY, 'oLush');
1489     //level.MarkTileAsWet(tileX, tileY);
1490     return;
1491   }
1493   if (tile == ",") {
1494     // k8: it looks like a brick in the water; dunno why it is done this way
1495     //     it seems that water brick is created to mark it as "water"
1496     //k8:???level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1497     if (global.randRoom(1, 2) == 1) {
1498       level.MakeMapTile(tileX, tileY, 'oLush');
1499       //level.MarkTileAsWet(tileX, tileY);
1500     }
1501     return;
1502   }
1504   if (tile == "J") {
1505     // k8: it looks like a brick in the water; dunno why it is done this way
1506     //     it seems that water brick is created to mark it as "water"
1507     level.MakeMapTile(tileX, tileY, 'oWaterSwim');
1508     level.MakeMapObject(tileX*16, tileY*16, 'oJaws'); // jaws crates are done in jaws object
1509     return;
1510   }
1512   if (tile == "I") {
1513     level.MakeMapObject(tileX*16+16, tileY*16+12, 'oGoldIdol');
1514     // create trap activator
1515     auto obj = level.MakeMapObject(tileX+1, tileY+1, 'oTikiCurseRemoveBricks');
1516     obj.active = false; // force it here
1517     return;
1518   }
1520   if (tile == "C") {
1521     level.MakeMapObject(tileX*16+16, tileY*16+12, 'oCrystalSkull');
1522     // create trap activator
1523     auto obj = level.MakeMapObject(tileX+1, tileY+1, 'oTikiCurseRemoveBricks');
1524     obj.active = false; // force it here
1525     return;
1526   }
1528   if (tile == ".") {
1529     if (level.checkTileAtPoint(tileX*16, tileY*16)) return;
1530     auto obj = level.MakeMapTile(tileX, tileY, 'oLush');
1531     obj.shopWall = true;
1532     return;
1533   }
1535   if (tile == "Q") {
1536     if (shopType == 'Craps') level.MakeMapBackTile('bgDiceSign', 0, 0, 48, 32, tileX*16, tileY*16, 9004);
1537     return;
1538   }
1540   if (tile == "q") {
1541     //???: n = rand(1,6);
1542     auto obj = level.scrGenerateItem(tileX*16+8, tileY*16+8, GameLevel::GenItemSet.Craps);
1543     if (obj) obj.inDiceHouse = true;
1544     return;
1545   }
1547   if (tile == "+") {
1548     auto obj = level.MakeMapTile(tileX, tileY, /*'oSolid'*/'oSolidIceBlock');
1549     //obj.sprite_index = sIceBlock;
1550     obj.shopWall = true;
1551     return;
1552   }
1554   if (tile == "W") {
1555     if (global.murderer || global.thiefLevel > 0) {
1556            if (global.isDamsel) level.MakeMapBackTile('bgWanted', 32, 0, 32, 32, tileX*16, tileY*16, 9004);
1557       else if (global.isTunnelMan) level.MakeMapBackTile('bgWanted', 64, 0, 32, 32, tileX*16, tileY*16, 9004);
1558       else level.MakeMapBackTile('bgWanted', 0, 0, 32, 32, tileX*16, tileY*16, 9004);
1559     }
1560     return;
1561   }
1563   if (tile == "b") {
1564     auto obj = level.MakeMapTile(tileX, tileY, 'oBrickSmooth');
1565     obj.setSprite('sLushSmooth');
1566     obj.shopWall = true;
1567     return;
1568   }
1570   if (tile == "l") {
1571     level.MakeMapTile(tileX, tileY, (shopType == 'Kissing' ? 'oLampRed' : 'oLamp'));
1572     return;
1573   }
1575   if (tile == "K") {
1576     //auto obj = MonsterShopkeeper(level.MakeMapObject(tileX*16, tileY*16, 'oShopkeeper'));
1577     //if (obj) obj.style = shopType;
1578     level.scrLevGenShopkeeper(tileX*16, tileY*16, shopType);
1579     return;
1580   }
1582   if (tile == "k") {
1583          if (shopType == 'General') level.MakeMapTile(tileX, tileY, 'oSignGeneral');
1584     else if (shopType == 'Bomb') level.MakeMapTile(tileX, tileY, 'oSignBomb');
1585     else if (shopType == 'Weapon') level.MakeMapTile(tileX, tileY, 'oSignWeapon');
1586     else if (shopType == 'Clothing') level.MakeMapTile(tileX, tileY, 'oSignClothing');
1587     else if (shopType == 'Rare') level.MakeMapTile(tileX, tileY, 'oSignRare');
1588     else if (shopType == 'Craps') level.MakeMapTile(tileX, tileY, 'oSignCraps');
1589     else if (shopType == 'Kissing') level.MakeMapTile(tileX, tileY, 'oSignKissing');
1590     else level.MakeMapTile(tileX, tileY, 'oSign');
1591     return;
1592   }
1594   if (tile == "i") {
1595     level.scrShopItemsGen(tileX*16, tileY*16, shopType);
1596     return;
1597   }
1599   if (tile == "u") {
1600     auto die = level.MakeMapObject(tileX*16+8, tileY*16+8, 'oDice');
1601     if (die) {
1602       die.forSale = true;
1603       die.shopType = 'Craps';
1604     }
1605     return;
1606   }
1608   if (tile == "D") {
1609     auto obj = level.MakeMapObject(tileX*16+8, tileY*16+8, 'oDamsel');
1610     if (obj) {
1611       obj.forSale = true;
1612       obj.status = MonsterDamsel::SLAVE;
1613       obj.shopType = 'Kissing';
1614     }
1615     return;
1616   }
1618   if (tile == "B") {
1619     auto obj = MapTileLushTrapBlock(level.MakeMapTile(tileX, tileY, 'oTrapBlock'));
1620     if (obj) {
1621       auto idol = level.findNearestObject(tileX*16, tileY*16, delegate bool (MapObject o) {
1622         return (o isa ItemGoldIdol);
1623       });
1624       obj.deathTimer = 40-abs(obj.ix-(idol ? idol.ix-8 : 0));
1625       //writeln("DEATH TIMER: ", obj.deathTimer);
1626       if (obj.deathTimer < 0) obj.deathTimer = 0;
1627     }
1628     return;
1629   }
1631   if (tile == "x") {
1632     level.MakeMapTile(tileX+0, tileY, 'oSacAltarLeft');
1633     level.MakeMapTile(tileX+1, tileY, 'oSacAltarRight');
1634     level.MakeMapBackTile('bgKaliBody', 0, 0, 64, 64, tileX*16-16, tileY*16-48, 10001);
1635     level.MakeMapTile(tileX+1, tileY-4, 'oKaliHead');
1636     return;
1637   }
1639   if (tile == "p") {
1640     int xpos = tileX*16, ypos = tileY*16;
1641     if (global.randRoom(1, 2) == 1) level.MakeMapObject(xpos, ypos, 'oFakeBones'); //k8: was without `==`
1642     else level.scrLevGenCreateJar(xpos+8, ypos+10);
1643     return;
1644   }
1646   if (tile == "T") {
1647     // tree
1648     int xpos = tileX*16, ypos = tileY*16;
1649     level.MakeMapTileAtPix(xpos, ypos, 'oTree');
1650     int n = 0;
1651     int tx = xpos;
1652     int ty = ypos-16;
1653     bool b1 = false;
1654     bool b2 = false;
1655     foreach (int m; 0..5) {
1656       if (global.randRoom(0, m) > 2) break;
1657       if (!level.isSolidAtPoint(tx, ty-16) &&
1658           !level.isSolidAtPoint(tx-16, ty-16) &&
1659           !level.isSolidAtPoint(tx+16, ty-16))
1660       {
1661         level.MakeMapTileAtPix(tx, ty, 'oTree');
1662         if (m < 4) {
1663           if (!b1 && global.randRoom(1, 5) < 4) {
1664             level.MakeMapTileAtPix(tx+16, ty, 'oTreeBranch');
1665             b1 = true;
1666           } else if (b1) {
1667             b1 = false;
1668           }
1669           if (!b2 && global.randRoom(1, 5) < 4) {
1670             level.MakeMapTileAtPix(tx-16, ty, 'oTreeBranch');
1671             b2 = true;
1672           } else if (b2) {
1673             b2 = false;
1674           }
1675         }
1676       } else {
1677         break;
1678       }
1679       ty -= 16;
1680     }
1681     level.MakeMapTileAtPix(tx-16, ty+16, 'oLeaves');
1682     level.MakeMapTileAtPix(tx+16, ty+16, 'oLeaves');
1683     return;
1684   }
1686   FatalError("INVALID JUNGLE BLOCK: '%s'", string.fromChar(tile));
1690 // ////////////////////////////////////////////////////////////////////////// //
1691 final bool cbIsObjectXMarket (MapObject o) { return false/*!(o isa ObjXMarketEntrance)*/; }
1692 final bool cbIsSolidOrWater (MapTile t) { return (t.solid || t.water || t.lava); }
1693 final bool cbIsWater (MapTile t) { return (t.water || t.lava); }
1694 final bool cbIsSolidOrSpikes (MapTile t) { return (t.solid || t.spikes); }
1695 final bool cbIsSpikes (MapTile t) { return (t.spikes); }
1698 override void genEntityAt (int tileX, int tileY) {
1699   auto global = levgen.global;
1700   auto level = levgen.level;
1702   int x = tileX*16, y = tileY*16;
1704   if (global.randRoom(1, 100) == 1 && !level.isSolidAtPoint(x, y-16)) {
1705     level.MakeMapBackTile('bgTrees', 0, 0, 16, 48, x, y-32, 9998);
1706   }
1708   if (level.isInShop(tileX, tileY)) return;
1710   MapTile t = level.getTileAtGrid(tileX, tileY);
1712   if (tileY > 2 && level.isSolidAtPoint(x, y-16) && global.genMarketEntrance && !global.madeMarketEntrance) {
1713     auto obj = level.isSolidAtPoint(x, y-16);
1714     if (!obj.altar && !obj.tree && !obj.invincible && global.randRoom(1, global.marketChance) <= 1) {
1715       level.MakeMapTile(tileX, tileY-1, 'oXMarket');
1716       t.invincible = true;
1717       global.madeMarketEntrance = true;
1718     } else {
1719       global.marketChance -= 1;
1720     }
1721   } else if ((t && t.isInstanceAlive && !t.altar && !t.tree) && y != 0 &&
1722              !level.checkTilesInRect(x, y-32, 16, 32) &&
1723              !level.isObjectInRect(x, y-16, 16, 16, &level.cbIsObjectEnemy) &&
1724              (!level.isSolidAtPoint(x-16, y) || !level.isSolidAtPoint(x+16, y)) &&
1725              level.isSolidAtPoint(x, y+16) &&
1726              !level.isObjectAtPoint(x, y, &cbIsObjectXMarket) &&
1727              //!isInShop(x, y) && // in the original
1728              level.calcNearestEnterDist(x, y) > 64)
1729   {
1730     if (global.darkLevel && !level.checkTileAtPoint(x, y-32, &level.cbCollisionWater) && global.randRoom(1, 20) == 1) {
1731       //level.MakeMapObject(x, y-32, 'oTikiTorch');
1732       level.MakeMapTile(tileX, tileY-2, 'oTikiTorch');
1733     } else if (!level.checkTilesInRect(tileX*16, (tileY-1)*16, 16, 16*2, castClass:MapTileSpearTrapBase) &&
1734                x != 160 && x != 176 && x != 320 && x != 336 && x != 480 && x != 496 &&
1735                global.randRoom(1, trunc(ceil(12.0/global.config.trapMult))) == 1) {
1736       // don't create tiki traps near the entrance
1737       if (level.calcNearestEnterDist(x, y) >= 32) {
1738         level.RemoveMapTileFromGrid(tileX, tileY-1, "spear trap top");
1739         level.MakeMapTile(tileX, tileY-1, (global.darkLevel ? 'oSpearTrapTopLit' : 'oSpearTrapTop'));
1740         level.RemoveMapTileFromGrid(tileX, tileY, "spear trap bottom");
1741         level.MakeMapTile(tileX, tileY, 'oSpearTrapBottom');
1742         if (t && t.isInstanceAlive) {
1743           t.cleanDeath = true;
1744           t.instanceRemove();
1745         }
1746         t = none;
1747       }
1748     }
1749   }
1751   if (t && t.isInstanceAlive && !t.altar) {
1752     if (global.cemetary) level.scrTreasureGen(x, y, 10); else level.scrTreasureGen(x, y);
1753   }
1755   int roomX, roomY;
1756   level.tileXY2roomXY(tileX, tileY-1, roomX, roomY); //k8: why -1?
1758   // enemies
1759   if (roomX == level.startRoomX && roomY == level.startRoomY) return;
1761   if (!level.checkTileAtPoint(x, y+16, &cbIsSolidOrWater) &&
1762       !level.checkTileAtPoint(x, y+32, &cbIsSolidOrWater))
1763   {
1764     {
1765       int n = (global.cemetary ? 60 : 80);
1766            if (global.darkLevel && global.randRoom(1, 40) == 1) level.MakeMapObject(x, y+16, 'oScarab');
1767       else if (global.randRoom(1, trunc(ceil(float(n)/global.config.enemyMult))) == 1) level.MakeMapObject(x, y+16, 'oBat');
1768       // else if (randRoom(1, 40) == 1) MakeMapObject(x, y+16, 'oSpiderHang'); // in the original
1769     }
1771     if (!level.isSolidAtPoint(x, y-16) &&
1772         !level.isObjectAtPoint(x, y, &level.cbIsObjectEnemy) &&
1773         !level.checkTileAtPoint(x, y, &cbIsSpikes))
1774     {
1775       if (global.cemetary) {
1776              if (global.randRoom(1, trunc(ceil(25.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, 'oZombie');
1777         else if (global.randRoom(1, trunc(ceil(160.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, 'oVampire');
1778       } else if (!level.checkTileAtPoint(x, y-16, &cbIsWater)) {
1779         int n = (global.blackMarket && (y%128 == 0) ? 0 : 1); // to prevent mantraps from spawning near shopkeepers in black market
1780              if (global.randRoom(1, trunc(ceil(60.0/global.config.enemyMult))) == n) level.MakeMapObject(x, y-16, 'oManTrap');
1781         else if (global.randRoom(1, trunc(ceil(60.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, 'oCaveman');
1782         else if (global.randRoom(1, trunc(ceil(120.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, 'oFireFrog');
1783         else if (global.randRoom(1, trunc(ceil(30.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, level.scrGenGetFrogType());
1784       }
1785       else if (global.randRoom(1, trunc(ceil(120.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, 'oFireFrog');
1786       else if (global.randRoom(1, trunc(ceil(30.0/global.config.enemyMult))) == 1) level.MakeMapObject(x, y-16, level.scrGenGetFrogType());
1787     }
1788   }
1792 defaultproperties {
1793   rgLevelType = 1;
1794   rgBizarre = false;