veloren_world/site2/plot/
desert_city_multiplot.rs

1use super::*;
2use crate::{
3    Land,
4    assets::AssetHandle,
5    site2::gen::{PrimitiveTransform, spiral_staircase},
6    util::{DIAGONALS, NEIGHBORS, RandomField, Sampler},
7};
8use common::{
9    generation::{EntityInfo, SpecialEntity},
10    terrain::{Block, BlockKind, SpriteKind, Structure as PrefabStructure, StructuresGroup},
11};
12use lazy_static::lazy_static;
13use rand::prelude::*;
14use std::sync::Arc;
15use vek::*;
16
17enum PlotKind {
18    MarketHall {
19        floors: i32,
20        towers: [(WatchTower, Vec2<i32>); 4],
21    },
22    Multiple {
23        subplots: Vec<(SubPlotKind, Vec2<i32>)>,
24    },
25}
26
27enum SubPlotKind {
28    WorkshopHouse { floors: i32 },
29    Library,
30    WatchTower(WatchTower),
31    PalmTree,
32    AnimalShed,
33}
34
35struct WatchTower {
36    length: i32,
37    height: i32,
38}
39
40/// Represents house data generated by the `generate()` method
41pub struct DesertCityMultiPlot {
42    /// Tile position of the door tile
43    pub door_tile: Vec2<i32>,
44    /// Axis aligned bounding region for the house
45    bounds: Aabr<i32>,
46    /// Approximate altitude of the door tile
47    pub(crate) alt: i32,
48    diameter: i32,
49    plot_kind: PlotKind,
50    campfire: bool,
51}
52
53impl DesertCityMultiPlot {
54    pub fn generate(
55        land: &Land,
56        rng: &mut impl Rng,
57        site: &Site,
58        door_tile: Vec2<i32>,
59        door_dir: Vec2<i32>,
60        tile_aabr: Aabr<i32>,
61        campfire: bool,
62        alt: Option<i32>,
63    ) -> Self {
64        let door_tile_pos = site.tile_center_wpos(door_tile);
65        let bounds = Aabr {
66            min: site.tile_wpos(tile_aabr.min),
67            max: site.tile_wpos(tile_aabr.max),
68        };
69        let diameter = 10 + (bounds.max.x - bounds.min.x).min(bounds.max.y - bounds.min.y);
70        let plot_kind = match rng.gen_range(0..5) {
71            0 => {
72                let floors = rng.gen_range(2..5);
73                let towers = {
74                    let center = bounds.center();
75                    let room_length = diameter / 4;
76                    let tower_length = diameter / 14;
77                    let mut tower = |i| {
78                        let tower_center = center
79                            + DIAGONALS[i]
80                                * (Vec2::new(
81                                    room_length + tower_length + 1,
82                                    room_length + 2 * tower_length,
83                                ));
84                        let height = rng.gen_range(25..35);
85                        (
86                            WatchTower {
87                                length: tower_length,
88                                height,
89                            },
90                            tower_center,
91                        )
92                    };
93                    [tower(0), tower(1), tower(2), tower(3)]
94                };
95                PlotKind::MarketHall { floors, towers }
96            },
97            _ => {
98                let mut subplot_kind = || match rng.gen_range(0..15) {
99                    0..=5 => SubPlotKind::WorkshopHouse {
100                        floors: rng.gen_range(1..4),
101                    },
102                    6..=7 => SubPlotKind::Library,
103                    8..=9 => SubPlotKind::AnimalShed,
104                    10..=11 => SubPlotKind::WatchTower(WatchTower {
105                        length: diameter / 14,
106                        height: rng.gen_range(25..35),
107                    }),
108                    _ => SubPlotKind::PalmTree,
109                };
110                let subplot_center = |i| {
111                    let corner_pos = bounds.min + diameter / 5;
112                    corner_pos + SQUARE_4[i] * (diameter / 2 - 5)
113                };
114
115                let sw_plot = (subplot_kind(), subplot_center(0));
116                let se_plot = (subplot_kind(), subplot_center(1));
117                let nw_plot = (subplot_kind(), subplot_center(2));
118                let ne_plot = (subplot_kind(), subplot_center(3));
119
120                PlotKind::Multiple {
121                    subplots: vec![ne_plot, se_plot, sw_plot, nw_plot],
122                }
123            },
124        };
125        Self {
126            bounds,
127            door_tile: door_tile_pos,
128            alt: alt.unwrap_or_else(|| {
129                land.get_alt_approx(site.tile_center_wpos(door_tile + door_dir)) as i32
130            }),
131            diameter,
132            plot_kind,
133            campfire,
134        }
135    }
136}
137
138impl Structure for DesertCityMultiPlot {
139    #[cfg(feature = "use-dyn-lib")]
140    const UPDATE_FN: &'static [u8] = b"render_desertcitymultiplot\0";
141
142    #[cfg_attr(feature = "be-dyn-lib", export_name = "render_desertcitymultiplot")]
143    fn render_inner(&self, _site: &Site, _land: &Land, painter: &Painter) {
144        let sandstone = Fill::Sampling(Arc::new(|center| {
145            Some(match (RandomField::new(0).get(center)) % 37 {
146                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
147                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
148                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
149                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
150                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
151            })
152        }));
153        let sandstone_broken = Fill::Sampling(Arc::new(|center| {
154            Some(match (RandomField::new(0).get(center)) % 42 {
155                0..=8 => Block::new(BlockKind::Rock, Rgb::new(245, 212, 129)),
156                9..=17 => Block::new(BlockKind::Rock, Rgb::new(246, 214, 133)),
157                18..=26 => Block::new(BlockKind::Rock, Rgb::new(247, 216, 136)),
158                27..=35 => Block::new(BlockKind::Rock, Rgb::new(248, 219, 142)),
159                36..=40 => Block::new(BlockKind::Air, Rgb::new(0, 0, 0)),
160                _ => Block::new(BlockKind::Rock, Rgb::new(235, 178, 99)),
161            })
162        }));
163        let wood = Fill::Brick(BlockKind::Wood, Rgb::new(71, 33, 11), 12);
164        let base = self.alt + 1;
165        let center = self.bounds.center();
166        // Fence
167        painter
168            .aabb(Aabb {
169                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
170                max: Vec2::new(self.bounds.min.x + 2, self.bounds.max.y).with_z(base + 2),
171            })
172            .union(painter.aabb(Aabb {
173                min: Vec2::new(self.bounds.max.x - 1, self.bounds.min.y + 1).with_z(base - 20),
174                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
175            }))
176            .union(painter.aabb(Aabb {
177                min: Vec2::new(self.bounds.min.x + 1, self.bounds.min.y + 1).with_z(base - 20),
178                max: Vec2::new(self.bounds.max.x, self.bounds.min.y + 2).with_z(base + 2),
179            }))
180            .union(painter.aabb(Aabb {
181                min: Vec2::new(self.bounds.min.x + 1, self.bounds.max.y - 1).with_z(base - 20),
182                max: Vec2::new(self.bounds.max.x, self.bounds.max.y).with_z(base + 2),
183            }))
184            .fill(sandstone_broken.clone());
185
186        // Gate1
187        painter
188            .aabb(Aabb {
189                min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base - 20),
190                max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
191            })
192            .fill(sandstone.clone());
193
194        painter
195            .aabb(Aabb {
196                min: Vec2::new(self.bounds.min.x + 1, center.y - 3).with_z(base + 9),
197                max: Vec2::new(self.bounds.max.x, center.y - 1).with_z(base + 10),
198            })
199            .clear();
200        painter
201            .aabb(Aabb {
202                min: Vec2::new(self.bounds.min.x + 1, center.y + 1).with_z(base + 9),
203                max: Vec2::new(self.bounds.max.x, center.y + 3).with_z(base + 10),
204            })
205            .clear();
206        painter
207            .aabb(Aabb {
208                min: Vec2::new(self.bounds.min.x + 2, center.y - 3).with_z(base + 8),
209                max: Vec2::new(self.bounds.max.x - 1, center.y + 3).with_z(base + 10),
210            })
211            .clear();
212        painter
213            .aabb(Aabb {
214                min: Vec2::new(self.bounds.min.x + 3, center.y - 3).with_z(base - 20),
215                max: Vec2::new(self.bounds.max.x - 2, center.y + 3).with_z(base + 10),
216            })
217            .clear();
218        // Gate2
219        painter
220            .aabb(Aabb {
221                min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base - 20),
222                max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
223            })
224            .fill(sandstone.clone());
225        painter
226            .aabb(Aabb {
227                min: Vec2::new(center.x + 2, self.bounds.min.y + 1).with_z(base + 9),
228                max: Vec2::new(center.x + 4, self.bounds.max.y).with_z(base + 10),
229            })
230            .clear();
231        painter
232            .aabb(Aabb {
233                min: Vec2::new(center.x - 2, self.bounds.min.y + 1).with_z(base + 9),
234                max: Vec2::new(center.x, self.bounds.max.y).with_z(base + 10),
235            })
236            .clear();
237        painter
238            .aabb(Aabb {
239                min: Vec2::new(center.x - 2, self.bounds.min.y + 2).with_z(base + 8),
240                max: Vec2::new(center.x + 4, self.bounds.max.y - 1).with_z(base + 10),
241            })
242            .clear();
243        painter
244            .aabb(Aabb {
245                min: Vec2::new(center.x - 2, self.bounds.min.y + 3).with_z(base - 20),
246                max: Vec2::new(center.x + 4, self.bounds.max.y - 2).with_z(base + 10),
247            })
248            .clear();
249        // gate clear
250        painter
251            .aabb(Aabb {
252                min: Vec2::new(self.bounds.min.x + 1, center.y - 2).with_z(base),
253                max: Vec2::new(self.bounds.max.x, center.y + 2).with_z(base + 7),
254            })
255            .clear();
256        painter
257            .aabb(Aabb {
258                min: Vec2::new(center.x - 1, self.bounds.min.y + 1).with_z(base),
259                max: Vec2::new(center.x + 3, self.bounds.max.y).with_z(base + 7),
260            })
261            .clear();
262        // Foundation
263        painter
264            .aabb(Aabb {
265                min: (self.bounds.min + 1).with_z(base - 20),
266                max: (self.bounds.max).with_z(base),
267            })
268            .fill(sandstone.clone());
269
270        // buildings
271        match &self.plot_kind {
272            // Market Hall with Watchtowers
273            PlotKind::MarketHall { floors, towers } => {
274                for floor in 0..*floors {
275                    let room_height = self.diameter / 6;
276                    let floor_level = base + (room_height * floor);
277                    let room_length = (self.diameter / 4) - (2 * floor);
278                    // Windowsills
279                    painter
280                        .aabb(Aabb {
281                            min: Vec2::new(center.x - room_length - 1, center.y)
282                                .with_z(floor_level + 1),
283                            max: Vec2::new(center.x + room_length + 1, center.y + 2)
284                                .with_z(floor_level + 2),
285                        })
286                        .fill(wood.clone());
287                    // Room
288                    painter
289                        .aabb(Aabb {
290                            min: Vec2::new(center.x - room_length, center.y - room_length + 3)
291                                .with_z(floor_level),
292                            max: Vec2::new(center.x + room_length, center.y + room_length - 1)
293                                .with_z(floor_level + room_height),
294                        })
295                        .fill(sandstone.clone());
296                    // Window Sprites
297                    painter
298                        .aabb(Aabb {
299                            min: Vec2::new(center.x - room_length, center.y)
300                                .with_z(floor_level + 2),
301                            max: Vec2::new(center.x + room_length, center.y + 2)
302                                .with_z(floor_level + 5),
303                        })
304                        .fill(Fill::Block(
305                            Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
306                        ));
307                    // Clear Room
308                    painter
309                        .aabb(Aabb {
310                            min: Vec2::new(center.x - room_length + 1, center.y - room_length + 4)
311                                .with_z(floor_level),
312                            max: Vec2::new(center.x + room_length - 1, center.y + room_length - 2)
313                                .with_z(floor_level + room_height - 2),
314                        })
315                        .clear();
316                    // Overhang1
317                    painter
318                        .aabb(Aabb {
319                            min: Vec2::new(center.x - room_length + 1, center.y + room_length - 1)
320                                .with_z(floor_level + room_height - 1),
321                            max: Vec2::new(center.x + room_length - 1, center.y + room_length)
322                                .with_z(floor_level + room_height),
323                        })
324                        .fill(wood.clone());
325                    // Overhang2
326                    painter
327                        .aabb(Aabb {
328                            min: Vec2::new(center.x + room_length, center.y - room_length + 2)
329                                .with_z(floor_level + room_height - 1),
330                            max: Vec2::new(center.x + room_length + 1, center.y + room_length - 2)
331                                .with_z(floor_level + room_height),
332                        })
333                        .fill(wood.clone());
334                    // Overhang3
335                    painter
336                        .aabb(Aabb {
337                            min: Vec2::new(center.x - room_length - 1, center.y - room_length + 4)
338                                .with_z(floor_level + room_height - 1),
339                            max: Vec2::new(center.x - room_length, center.y + room_length - 2)
340                                .with_z(floor_level + room_height),
341                        })
342                        .fill(wood.clone());
343                    // Door Frame
344                    painter
345                        .aabb(Aabb {
346                            min: Vec2::new(center.x - 2, center.y + room_length - 1)
347                                .with_z(floor_level),
348                            max: Vec2::new(center.x + 2, center.y + room_length)
349                                .with_z(floor_level + 5),
350                        })
351                        .fill(sandstone.clone());
352                    // Clear Door
353                    painter
354                        .aabb(Aabb {
355                            min: Vec2::new(center.x - 1, center.y + room_length - 2)
356                                .with_z(floor_level),
357                            max: Vec2::new(center.x + 1, center.y + room_length)
358                                .with_z(floor_level + 4),
359                        })
360                        .clear();
361                    // Remove Terrain in front of doors
362                    painter
363                        .aabb(Aabb {
364                            min: Vec2::new(center.x - 2, center.y + room_length)
365                                .with_z(floor_level),
366                            max: Vec2::new(center.x + 2, center.y + room_length + 4)
367                                .with_z(floor_level + 5),
368                        })
369                        .clear();
370                    // Stairs for each storey
371                    painter
372                        .ramp_inset(
373                            Aabb {
374                                min: Vec2::new(center.x - room_length, center.y - room_length + 1)
375                                    .with_z(floor_level),
376                                max: Vec2::new(center.x + room_length, center.y - room_length + 3)
377                                    .with_z(floor_level + room_height),
378                            },
379                            2 * room_length,
380                            Dir::X,
381                        )
382                        .fill(sandstone.clone());
383                    //interior room compartment with entries
384                    painter
385                        .aabb(Aabb {
386                            min: Vec2::new(
387                                center.x - (2 * room_length / 3) + 1,
388                                center.y - (2 * room_length / 3) + 4,
389                            )
390                            .with_z(floor_level),
391                            max: Vec2::new(
392                                center.x + (2 * room_length / 3) - 1,
393                                center.y + (2 * room_length / 3) - 2,
394                            )
395                            .with_z(floor_level + room_height - 2),
396                        })
397                        .fill(sandstone.clone());
398
399                    painter
400                        .aabb(Aabb {
401                            min: Vec2::new(
402                                center.x - (2 * room_length / 3) + 2,
403                                center.y - (2 * room_length / 3) + 5,
404                            )
405                            .with_z(floor_level),
406                            max: Vec2::new(
407                                center.x + (2 * room_length / 3) - 2,
408                                center.y + (2 * room_length / 3) - 3,
409                            )
410                            .with_z(floor_level + room_height - 2),
411                        })
412                        .clear();
413
414                    painter
415                        .aabb(Aabb {
416                            min: Vec2::new(
417                                center.x - (room_length / 6),
418                                center.y - (2 * room_length / 3) + 4,
419                            )
420                            .with_z(floor_level),
421                            max: Vec2::new(
422                                center.x + (room_length / 6),
423                                center.y + (2 * room_length / 3) - 2,
424                            )
425                            .with_z(floor_level + 3),
426                        })
427                        .clear();
428                    painter
429                        .aabb(Aabb {
430                            min: Vec2::new(
431                                center.x - (2 * room_length / 3) + 1,
432                                center.y + 1 + (room_length / 6),
433                            )
434                            .with_z(floor_level),
435                            max: Vec2::new(
436                                center.x + (2 * room_length / 3) - 1,
437                                center.y + 1 - (room_length / 6),
438                            )
439                            .with_z(floor_level + 3),
440                        })
441                        .clear();
442
443                    // interior room Wall Lamps
444                    painter
445                        .aabb(Aabb {
446                            min: Vec2::new(center.x - 1, center.y - (2 * room_length / 3) + 5)
447                                .with_z(floor_level + 4),
448                            max: Vec2::new(center.x + 1, center.y - (2 * room_length / 3) + 6)
449                                .with_z(floor_level + 5),
450                        })
451                        .fill(Fill::Block(
452                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
453                        ));
454
455                    painter
456                        .aabb(Aabb {
457                            min: Vec2::new(center.x - 1, center.y + (2 * room_length / 3) - 2)
458                                .with_z(floor_level + 4),
459                            max: Vec2::new(center.x + 1, center.y + (2 * room_length / 3) - 1)
460                                .with_z(floor_level + 5),
461                        })
462                        .fill(Fill::Block(
463                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
464                        ));
465
466                    // Wall Lamps
467                    painter
468                        .aabb(Aabb {
469                            min: Vec2::new(center.x - 1, center.y - room_length + 4)
470                                .with_z(floor_level + 4),
471                            max: Vec2::new(center.x + 1, center.y - room_length + 5)
472                                .with_z(floor_level + 5),
473                        })
474                        .fill(Fill::Block(
475                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
476                        ));
477
478                    painter
479                        .aabb(Aabb {
480                            min: Vec2::new(center.x - 1, center.y + room_length)
481                                .with_z(floor_level + 4),
482                            max: Vec2::new(center.x + 1, center.y + room_length + 1)
483                                .with_z(floor_level + 5),
484                        })
485                        .fill(Fill::Block(
486                            Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
487                        ));
488
489                    // Floor specific stuff
490                    match floor {
491                        // Ground level room furniture - bank
492                        0 => {
493                            for dir in NEIGHBORS {
494                                let pos = center + dir * 4;
495                                painter.owned_resource_sprite(
496                                    pos.with_z(floor_level),
497                                    SpriteKind::Crate,
498                                    0,
499                                );
500                            }
501                            for dir in NEIGHBORS {
502                                let pos = center + dir * 8;
503                                painter.sprite(pos.with_z(floor_level), SpriteKind::DrawerSmall);
504                            }
505
506                            for dir in SQUARE_4 {
507                                let corner_pos =
508                                    Vec2::new(center.x - 4, center.y - room_length + 4);
509                                let planter_pos = Vec2::new(
510                                    corner_pos.x + dir.x * 7,
511                                    corner_pos.y + dir.y * ((2 * room_length) - 7),
512                                );
513                                painter.rotated_sprite(
514                                    planter_pos.with_z(floor_level),
515                                    SpriteKind::DrawerMedium,
516                                    4 - (4 * dir.y) as u8,
517                                );
518                            }
519                        },
520                        // First floor room furniture
521                        1 => {
522                            for dir in NEIGHBORS {
523                                let pos = center + dir * 7;
524                                painter.sprite(pos.with_z(floor_level), SpriteKind::Planter);
525                            }
526
527                            for dir in SQUARE_4 {
528                                let corner_pos =
529                                    Vec2::new(center.x - 4, center.y - room_length + 4);
530                                let planter_pos = Vec2::new(
531                                    corner_pos.x + dir.x * 7,
532                                    corner_pos.y + dir.y * ((2 * room_length) - 7),
533                                );
534                                painter.rotated_sprite(
535                                    planter_pos.with_z(floor_level),
536                                    SpriteKind::DrawerSmall,
537                                    4 - (4 * dir.y) as u8,
538                                );
539                            }
540                        },
541                        _ => {},
542                    }
543                    // On top floor, carve the roof terrace
544                    if floor == (*floors - 1) {
545                        painter
546                            .aabb(Aabb {
547                                min: Vec2::new(
548                                    center.x - room_length + 1,
549                                    center.y - room_length + 4,
550                                )
551                                .with_z(floor_level + room_height - 1),
552                                max: Vec2::new(
553                                    center.x + room_length - 1,
554                                    center.y + room_length - 2,
555                                )
556                                .with_z(floor_level + room_height),
557                            })
558                            .clear();
559                        painter
560                            .aabb(Aabb {
561                                min: Vec2::new(
562                                    center.x + room_length - 3,
563                                    center.y - room_length + 1,
564                                )
565                                .with_z(floor_level + room_height - 1),
566                                max: Vec2::new(
567                                    center.x + room_length - 1,
568                                    center.y - room_length + 4,
569                                )
570                                .with_z(floor_level + room_height),
571                            })
572                            .clear();
573                        // Roof Ornament
574                        painter
575                            .aabb(Aabb {
576                                min: Vec2::new(center.x - room_length, center.y + room_length - 2)
577                                    .with_z(floor_level + room_height),
578                                max: Vec2::new(center.x + room_length, center.y + room_length - 1)
579                                    .with_z(floor_level + room_height + 2),
580                            })
581                            .fill(sandstone.clone());
582                        painter
583                            .aabb(Aabb {
584                                min: Vec2::new(
585                                    center.x - room_length + 2,
586                                    center.y + room_length - 2,
587                                )
588                                .with_z(floor_level + room_height + 2),
589                                max: Vec2::new(
590                                    center.x + room_length - 2,
591                                    center.y + room_length - 1,
592                                )
593                                .with_z(floor_level + room_height + 3),
594                            })
595                            .fill(sandstone.clone());
596                        painter
597                            .aabb(Aabb {
598                                min: Vec2::new(center.x - 2, center.y + room_length - 2)
599                                    .with_z(floor_level + room_height + 3),
600                                max: Vec2::new(center.x + 2, center.y + room_length - 1)
601                                    .with_z(floor_level + room_height + 4),
602                            })
603                            .fill(sandstone.clone());
604                        // Wood Beams
605                        for dir in SQUARE_4 {
606                            let corner_pos =
607                                Vec2::new(center.x - room_length + 3, center.y - room_length + 7);
608                            let pos = Vec2::new(
609                                corner_pos.x + dir.x * ((2 * room_length) - 8),
610                                corner_pos.y + dir.y * ((2 * room_length) - 12),
611                            );
612                            painter
613                                .aabb(Aabb {
614                                    min: pos.with_z(floor_level + room_height - 1),
615                                    max: (pos + 1)
616                                        .with_z(floor_level + room_height + (room_height / 2)),
617                                })
618                                .fill(wood.clone());
619                        }
620                        painter
621                            .aabb(Aabb {
622                                min: Vec2::new(
623                                    center.x - room_length + 2,
624                                    center.y - room_length + 6,
625                                )
626                                .with_z(floor_level + room_height + (room_height / 2) - 1),
627                                max: Vec2::new(
628                                    center.x + room_length - 3,
629                                    center.y + room_length - 3,
630                                )
631                                .with_z(floor_level + room_height + (room_height / 2)),
632                            })
633                            .fill(wood.clone());
634
635                        painter
636                            .aabb(Aabb {
637                                min: Vec2::new(
638                                    center.x - room_length + 3,
639                                    center.y - room_length + 7,
640                                )
641                                .with_z(floor_level + room_height + (room_height / 2) - 1),
642                                max: Vec2::new(
643                                    center.x + room_length - 4,
644                                    center.y + room_length - 4,
645                                )
646                                .with_z(floor_level + room_height + (room_height / 2)),
647                            })
648                            .clear();
649
650                        for b in 0..(room_length - 3) {
651                            painter
652                                .aabb(Aabb {
653                                    min: Vec2::new(
654                                        center.x - room_length + 3 + (b * 2),
655                                        center.y - room_length + 5,
656                                    )
657                                    .with_z(floor_level + room_height + (room_height / 2)),
658                                    max: Vec2::new(
659                                        center.x - room_length + 4 + (b * 2),
660                                        center.y + room_length - 2,
661                                    )
662                                    .with_z(floor_level + room_height + (room_height / 2) + 1),
663                                })
664                                .fill(wood.clone());
665                        }
666                        // roof furniture
667                        for d in 0..2 {
668                            for dir in NEIGHBORS {
669                                let pos = center + dir * (3 + d * 3);
670                                painter.sprite(
671                                    pos.with_z(floor_level + room_height - 1),
672                                    SpriteKind::Planter,
673                                );
674                            }
675                        }
676                    }
677                }
678                // WatchTowers
679                for (tower, tower_center) in towers {
680                    // Tower Windowsills
681                    for h in 0..4 {
682                        painter
683                            .aabb(Aabb {
684                                min: Vec2::new(
685                                    tower_center.x - 1,
686                                    tower_center.y - tower.length - 1,
687                                )
688                                .with_z(base + 8 + (h * (tower.height / 5))),
689                                max: Vec2::new(
690                                    tower_center.x + 1,
691                                    tower_center.y + tower.length + 1,
692                                )
693                                .with_z(base + 9 + (h * (tower.height / 5))),
694                            })
695                            .fill(wood.clone());
696                    }
697                    for h in 0..4 {
698                        painter
699                            .aabb(Aabb {
700                                min: Vec2::new(
701                                    tower_center.x - tower.length - 1,
702                                    tower_center.y - 1,
703                                )
704                                .with_z(base + 8 + (h * (tower.height / 5))),
705                                max: Vec2::new(
706                                    tower_center.x + tower.length + 1,
707                                    tower_center.y + 1,
708                                )
709                                .with_z(base + 9 + (h * (tower.height / 5))),
710                            })
711                            .fill(wood.clone());
712                    }
713                    // Tower base
714                    painter
715                        .aabb(Aabb {
716                            min: (tower_center - tower.length - 1).with_z(base - 10),
717                            max: (tower_center + tower.length + 1).with_z(base + 6),
718                        })
719                        .fill(sandstone.clone());
720                    // Tower
721                    painter
722                        .aabb(Aabb {
723                            min: (tower_center - tower.length).with_z(base),
724                            max: (tower_center + tower.length).with_z(base + tower.height),
725                        })
726                        .fill(sandstone.clone());
727                    // Tower Windows
728                    for h in 0..4 {
729                        painter
730                            .aabb(Aabb {
731                                min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length)
732                                    .with_z(base + 9 + (h * (tower.height / 5))),
733                                max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length)
734                                    .with_z(base + 12 + (h * (tower.height / 5))),
735                            })
736                            .fill(Fill::Block(
737                                Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
738                            ));
739                    }
740                    for h in 0..4 {
741                        painter
742                            .aabb(Aabb {
743                                min: Vec2::new(tower_center.x - tower.length, tower_center.y - 1)
744                                    .with_z(base + 9 + (h * (tower.height / 5))),
745                                max: Vec2::new(tower_center.x + tower.length, tower_center.y + 1)
746                                    .with_z(base + 12 + (h * (tower.height / 5))),
747                            })
748                            .fill(Fill::Block(
749                                Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
750                            ));
751                    }
752                    // Tower entries1
753                    painter
754                        .aabb(Aabb {
755                            min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
756                                .with_z(base - 20),
757                            max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
758                                .with_z(base + 5),
759                        })
760                        .fill(sandstone.clone());
761                    painter
762                        .aabb(Aabb {
763                            min: Vec2::new(tower_center.x - tower.length - 4, tower_center.y - 1)
764                                .with_z(base),
765                            max: Vec2::new(tower_center.x + tower.length + 4, tower_center.y + 1)
766                                .with_z(base + 4),
767                        })
768                        .clear();
769                    // Tower entries2
770                    painter
771                        .aabb(Aabb {
772                            min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
773                                .with_z(base - 20),
774                            max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
775                                .with_z(base + 5),
776                        })
777                        .fill(sandstone.clone());
778                    painter
779                        .aabb(Aabb {
780                            min: Vec2::new(tower_center.x - 1, tower_center.y - tower.length - 4)
781                                .with_z(base),
782                            max: Vec2::new(tower_center.x + 1, tower_center.y + tower.length + 4)
783                                .with_z(base + 4),
784                        })
785                        .clear();
786                    // clear Tower base
787                    painter
788                        .aabb(Aabb {
789                            min: (tower_center - tower.length).with_z(base),
790                            max: (tower_center + tower.length).with_z(base + 5),
791                        })
792                        .clear();
793                    // Tower Entry Lamps
794                    for d in 0..2 {
795                        painter
796                            .aabb(Aabb {
797                                min: Vec2::new(
798                                    tower_center.x - 1,
799                                    tower_center.y - tower.length - 3
800                                        + (d * ((2 * tower.length) + 6)),
801                                )
802                                .with_z(base + 4),
803                                max: Vec2::new(
804                                    tower_center.x + 1,
805                                    tower_center.y - tower.length - 2
806                                        + (d * ((2 * tower.length) + 4)),
807                                )
808                                .with_z(base + 5),
809                            })
810                            .fill(Fill::Block(
811                                Block::air(SpriteKind::WallLampSmall)
812                                    .with_ori(0 + (4 * d) as u8)
813                                    .unwrap(),
814                            ));
815                    }
816                    // Platform
817                    painter
818                        .aabb(Aabb {
819                            min: (tower_center - tower.length - 2).with_z(base + tower.height),
820                            max: (tower_center + tower.length + 2).with_z(base + tower.height + 4),
821                        })
822                        .fill(sandstone.clone());
823                    painter
824                        .aabb(Aabb {
825                            min: (tower_center - tower.length - 1).with_z(base + tower.height + 2),
826                            max: (tower_center + tower.length + 1).with_z(base + tower.height + 4),
827                        })
828                        .clear();
829
830                    painter
831                        .aabb(Aabb {
832                            min: Vec2::new(tower_center.x - tower.length - 2, tower_center.y - 2)
833                                .with_z(base + tower.height + 3),
834                            max: Vec2::new(tower_center.x + tower.length + 2, tower_center.y + 2)
835                                .with_z(base + tower.height + 4),
836                        })
837                        .clear();
838                    painter
839                        .aabb(Aabb {
840                            min: Vec2::new(tower_center.x - 2, tower_center.y - tower.length - 2)
841                                .with_z(base + tower.height + 3),
842                            max: Vec2::new(tower_center.x + 2, tower_center.y + tower.length + 2)
843                                .with_z(base + tower.height + 4),
844                        })
845                        .clear();
846
847                    // clear Tower
848                    let tower_clear = painter.aabb(Aabb {
849                        min: (tower_center - tower.length + 1).with_z(base),
850                        max: (tower_center + tower.length - 1).with_z(base + tower.height + 3),
851                    });
852                    tower_clear.clear();
853                    // stairway
854                    let stair_radius = tower.length + 1;
855                    let stairs_clear = painter.aabb(Aabb {
856                        min: (tower_center - stair_radius).with_z(base),
857                        max: (tower_center + stair_radius).with_z(base + tower.height + 2),
858                    });
859                    stairs_clear
860                        .sample(spiral_staircase(
861                            tower_center.with_z(base + tower.height + 2),
862                            stair_radius as f32,
863                            0.5,
864                            (2 * tower.length) as f32,
865                        ))
866                        .intersect(tower_clear)
867                        .fill(sandstone.clone());
868                }
869            },
870            PlotKind::Multiple { subplots } => {
871                // House, Workshop, Library, Palm, WatchTower
872                for (subplot_kind, subplot_center) in subplots {
873                    match subplot_kind {
874                        // House or Workshop (one storey house)
875                        SubPlotKind::WorkshopHouse { floors } => {
876                            for floor in 0..*floors {
877                                let room_height = self.diameter / 6;
878                                let floor_level = base + (room_height * floor);
879                                let room_length = (self.diameter / 7) - (2 * floor);
880                                // Windowsills
881                                painter
882                                    .aabb(Aabb {
883                                        min: Vec2::new(
884                                            subplot_center.x - room_length - 1,
885                                            subplot_center.y,
886                                        )
887                                        .with_z(floor_level + 1),
888                                        max: Vec2::new(
889                                            subplot_center.x + room_length + 1,
890                                            subplot_center.y + 2,
891                                        )
892                                        .with_z(floor_level + 2),
893                                    })
894                                    .fill(wood.clone());
895                                // Room
896                                painter
897                                    .aabb(Aabb {
898                                        min: Vec2::new(
899                                            subplot_center.x - room_length,
900                                            subplot_center.y - room_length + 3,
901                                        )
902                                        .with_z(floor_level),
903                                        max: Vec2::new(
904                                            subplot_center.x + room_length,
905                                            subplot_center.y + room_length - 1,
906                                        )
907                                        .with_z(floor_level + room_height),
908                                    })
909                                    .fill(sandstone.clone());
910                                // Window Sprites
911                                painter
912                                    .aabb(Aabb {
913                                        min: Vec2::new(
914                                            subplot_center.x - room_length,
915                                            subplot_center.y,
916                                        )
917                                        .with_z(floor_level + 2),
918                                        max: Vec2::new(
919                                            subplot_center.x + room_length,
920                                            subplot_center.y + 2,
921                                        )
922                                        .with_z(floor_level + 5),
923                                    })
924                                    .fill(Fill::Block(
925                                        Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
926                                    ));
927                                // Clear Room
928                                painter
929                                    .aabb(Aabb {
930                                        min: Vec2::new(
931                                            subplot_center.x - room_length + 1,
932                                            subplot_center.y - room_length + 4,
933                                        )
934                                        .with_z(floor_level),
935                                        max: Vec2::new(
936                                            subplot_center.x + room_length - 1,
937                                            subplot_center.y + room_length - 2,
938                                        )
939                                        .with_z(floor_level + room_height - 2),
940                                    })
941                                    .clear();
942                                // Overhang1
943                                painter
944                                    .aabb(Aabb {
945                                        min: Vec2::new(
946                                            subplot_center.x - room_length + 1,
947                                            subplot_center.y + room_length - 1,
948                                        )
949                                        .with_z(floor_level + room_height - 1),
950                                        max: Vec2::new(
951                                            subplot_center.x + room_length - 1,
952                                            subplot_center.y + room_length,
953                                        )
954                                        .with_z(floor_level + room_height),
955                                    })
956                                    .fill(wood.clone());
957                                // Overhang2
958                                painter
959                                    .aabb(Aabb {
960                                        min: Vec2::new(
961                                            subplot_center.x + room_length,
962                                            subplot_center.y - room_length + 2,
963                                        )
964                                        .with_z(floor_level + room_height - 1),
965                                        max: Vec2::new(
966                                            subplot_center.x + room_length + 1,
967                                            subplot_center.y + room_length - 2,
968                                        )
969                                        .with_z(floor_level + room_height),
970                                    })
971                                    .fill(wood.clone());
972                                // Overhang3
973                                painter
974                                    .aabb(Aabb {
975                                        min: Vec2::new(
976                                            subplot_center.x - room_length - 1,
977                                            subplot_center.y - room_length + 4,
978                                        )
979                                        .with_z(floor_level + room_height - 1),
980                                        max: Vec2::new(
981                                            subplot_center.x - room_length,
982                                            subplot_center.y + room_length - 2,
983                                        )
984                                        .with_z(floor_level + room_height),
985                                    })
986                                    .fill(wood.clone());
987                                // Door Frame
988                                painter
989                                    .aabb(Aabb {
990                                        min: Vec2::new(
991                                            subplot_center.x - 2,
992                                            subplot_center.y + room_length - 1,
993                                        )
994                                        .with_z(floor_level),
995                                        max: Vec2::new(
996                                            subplot_center.x + 2,
997                                            subplot_center.y + room_length,
998                                        )
999                                        .with_z(floor_level + 5),
1000                                    })
1001                                    .fill(sandstone.clone());
1002                                // Clear Door
1003                                painter
1004                                    .aabb(Aabb {
1005                                        min: Vec2::new(
1006                                            subplot_center.x - 1,
1007                                            subplot_center.y + room_length - 2,
1008                                        )
1009                                        .with_z(floor_level),
1010                                        max: Vec2::new(
1011                                            subplot_center.x + 1,
1012                                            subplot_center.y + room_length,
1013                                        )
1014                                        .with_z(floor_level + 4),
1015                                    })
1016                                    .clear();
1017                                // Remove Terrain in front of doors
1018                                painter
1019                                    .aabb(Aabb {
1020                                        min: Vec2::new(
1021                                            subplot_center.x - 2,
1022                                            subplot_center.y + room_length,
1023                                        )
1024                                        .with_z(floor_level),
1025                                        max: Vec2::new(
1026                                            subplot_center.x + 2,
1027                                            subplot_center.y + room_length + 4,
1028                                        )
1029                                        .with_z(floor_level + 5),
1030                                    })
1031                                    .clear();
1032                                // Stairs for each storey
1033                                painter
1034                                    .ramp_inset(
1035                                        Aabb {
1036                                            min: Vec2::new(
1037                                                subplot_center.x - room_length,
1038                                                subplot_center.y - room_length + 1,
1039                                            )
1040                                            .with_z(floor_level),
1041                                            max: Vec2::new(
1042                                                subplot_center.x + room_length,
1043                                                subplot_center.y - room_length + 3,
1044                                            )
1045                                            .with_z(floor_level + room_height),
1046                                        },
1047                                        2 * room_length,
1048                                        Dir::X,
1049                                    )
1050                                    .fill(sandstone.clone());
1051                                // Carve Roof Terrace
1052                                if floor == floors - 1 {
1053                                    painter
1054                                        .aabb(Aabb {
1055                                            min: Vec2::new(
1056                                                subplot_center.x - room_length + 1,
1057                                                subplot_center.y - room_length + 4,
1058                                            )
1059                                            .with_z(floor_level + room_height - 1),
1060                                            max: Vec2::new(
1061                                                subplot_center.x + room_length - 1,
1062                                                subplot_center.y + room_length - 2,
1063                                            )
1064                                            .with_z(floor_level + room_height),
1065                                        })
1066                                        .clear();
1067                                    painter
1068                                        .aabb(Aabb {
1069                                            min: Vec2::new(
1070                                                subplot_center.x + room_length - 3,
1071                                                subplot_center.y - room_length + 1,
1072                                            )
1073                                            .with_z(floor_level + room_height - 1),
1074                                            max: Vec2::new(
1075                                                subplot_center.x + room_length - 1,
1076                                                subplot_center.y - room_length + 4,
1077                                            )
1078                                            .with_z(floor_level + room_height),
1079                                        })
1080                                        .clear();
1081                                    // Roof Ornament
1082                                    painter
1083                                        .aabb(Aabb {
1084                                            min: Vec2::new(
1085                                                subplot_center.x - room_length,
1086                                                subplot_center.y + room_length - 2,
1087                                            )
1088                                            .with_z(floor_level + room_height),
1089                                            max: Vec2::new(
1090                                                subplot_center.x + room_length,
1091                                                subplot_center.y + room_length - 1,
1092                                            )
1093                                            .with_z(floor_level + room_height + 2),
1094                                        })
1095                                        .fill(sandstone.clone());
1096                                    painter
1097                                        .aabb(Aabb {
1098                                            min: Vec2::new(
1099                                                subplot_center.x - room_length + 2,
1100                                                subplot_center.y + room_length - 2,
1101                                            )
1102                                            .with_z(floor_level + room_height + 2),
1103                                            max: Vec2::new(
1104                                                subplot_center.x + room_length - 2,
1105                                                subplot_center.y + room_length - 1,
1106                                            )
1107                                            .with_z(floor_level + room_height + 3),
1108                                        })
1109                                        .fill(sandstone.clone());
1110                                    painter
1111                                        .aabb(Aabb {
1112                                            min: Vec2::new(
1113                                                subplot_center.x - 2,
1114                                                subplot_center.y + room_length - 2,
1115                                            )
1116                                            .with_z(floor_level + room_height + 3),
1117                                            max: Vec2::new(
1118                                                subplot_center.x + 2,
1119                                                subplot_center.y + room_length - 1,
1120                                            )
1121                                            .with_z(floor_level + room_height + 4),
1122                                        })
1123                                        .fill(sandstone.clone());
1124                                };
1125                                // furniture
1126                                if *floors == 1 {
1127                                    // Workshop in one-storey buildings
1128                                    painter
1129                                        .aabb(Aabb {
1130                                            min: (subplot_center - 2).with_z(floor_level),
1131                                            max: (subplot_center + 2)
1132                                                .with_z(floor_level + room_height + 1),
1133                                        })
1134                                        .fill(sandstone.clone());
1135
1136                                    painter
1137                                        .aabb(Aabb {
1138                                            min: (subplot_center - 2).with_z(floor_level + 1),
1139                                            max: (subplot_center + 2)
1140                                                .with_z(floor_level + room_height - 2),
1141                                        })
1142                                        .clear();
1143                                    painter
1144                                        .aabb(Aabb {
1145                                            min: (subplot_center - 1).with_z(floor_level),
1146                                            max: (subplot_center + 1)
1147                                                .with_z(floor_level + room_height + 1),
1148                                        })
1149                                        .clear();
1150                                    painter
1151                                        .aabb(Aabb {
1152                                            min: (subplot_center - 1).with_z(floor_level - 1),
1153                                            max: (subplot_center + 1).with_z(floor_level),
1154                                        })
1155                                        .fill(Fill::Block(Block::air(SpriteKind::Ember)));
1156                                    let mut stations = vec![
1157                                        SpriteKind::CraftingBench,
1158                                        SpriteKind::Forge,
1159                                        SpriteKind::SpinningWheel,
1160                                        SpriteKind::TanningRack,
1161                                        SpriteKind::Loom,
1162                                        SpriteKind::Anvil,
1163                                        SpriteKind::DismantlingBench,
1164                                        SpriteKind::RepairBench,
1165                                    ];
1166                                    'outer: for d in 0..2 {
1167                                        for dir in NEIGHBORS {
1168                                            if stations.is_empty() {
1169                                                break 'outer;
1170                                            }
1171                                            let position = subplot_center + dir * (4 + d * 2);
1172                                            let cr_station = stations.swap_remove(
1173                                                RandomField::new(0).get(position.with_z(base))
1174                                                    as usize
1175                                                    % stations.len(),
1176                                            );
1177                                            painter
1178                                                .sprite(position.with_z(floor_level), cr_station);
1179                                        }
1180                                    }
1181                                } else {
1182                                    // kitchen, bath, living room in buildings with 2-3 storeys
1183                                    match floor {
1184                                        0 => {
1185                                            // kitchen
1186                                            // cupboards / ovens / cushions / jugs
1187                                            for d in 0..2 {
1188                                                let a_pos = Vec2::new(
1189                                                    subplot_center.x + 3 - (d * 6),
1190                                                    subplot_center.y - room_length + 4,
1191                                                );
1192                                                painter.rotated_sprite(
1193                                                    a_pos.with_z(floor_level),
1194                                                    match (RandomField::new(0)
1195                                                        .get(a_pos.with_z(floor_level)))
1196                                                        % 2
1197                                                    {
1198                                                        0 => SpriteKind::CupboardArabic,
1199                                                        _ => SpriteKind::OvenArabic,
1200                                                    },
1201                                                    4,
1202                                                );
1203                                                let b_pos = Vec2::new(
1204                                                    subplot_center.x + 3 - (d * 6),
1205                                                    subplot_center.y + room_length - 3,
1206                                                );
1207                                                painter.rotated_sprite(
1208                                                    b_pos.with_z(floor_level),
1209                                                    match (RandomField::new(0)
1210                                                        .get(b_pos.with_z(floor_level)))
1211                                                        % 4
1212                                                    {
1213                                                        0 => SpriteKind::CupboardArabic,
1214                                                        1 => SpriteKind::OvenArabic,
1215                                                        2 => SpriteKind::CushionArabic,
1216                                                        _ => SpriteKind::JugArabic,
1217                                                    },
1218                                                    0,
1219                                                );
1220                                                // wall tables with varying items
1221                                                let c_pos = Vec2::new(
1222                                                    subplot_center.x - room_length
1223                                                        + 1
1224                                                        + (d * ((2 * room_length) - 3)),
1225                                                    subplot_center.y,
1226                                                );
1227                                                painter.rotated_sprite(
1228                                                    c_pos.with_z(floor_level),
1229                                                    SpriteKind::WallTableArabic,
1230                                                    6 - (4 * d) as u8,
1231                                                );
1232                                                painter.owned_resource_sprite(
1233                                                    c_pos.with_z(floor_level + 1),
1234                                                    match (RandomField::new(0)
1235                                                        .get(c_pos.with_z(floor_level)))
1236                                                        % 5
1237                                                    {
1238                                                        0 => SpriteKind::Melon,
1239                                                        1 => SpriteKind::JugAndBowlArabic,
1240                                                        2 => SpriteKind::Bowl,
1241                                                        3 => SpriteKind::JugArabic,
1242                                                        _ => SpriteKind::VialEmpty,
1243                                                    },
1244                                                    6 - (4 * d) as u8,
1245                                                );
1246                                            }
1247                                            // CookingPot, Cauldron
1248                                            painter.sprite(
1249                                                (subplot_center - 2).with_z(floor_level),
1250                                                SpriteKind::CookingPot,
1251                                            );
1252                                            painter.sprite(
1253                                                (subplot_center + 2).with_z(floor_level),
1254                                                SpriteKind::Cauldron,
1255                                            );
1256                                        },
1257                                        1 => {
1258                                            // living room
1259                                            // canape
1260                                            let canape_pos = Vec2::new(
1261                                                subplot_center.x - 4 + 7,
1262                                                subplot_center.y - room_length
1263                                                    + 5
1264                                                    + ((2 * room_length) - 9),
1265                                            );
1266
1267                                            painter.rotated_sprite(
1268                                                canape_pos.with_z(floor_level),
1269                                                SpriteKind::CanapeArabic,
1270                                                4_u8,
1271                                            );
1272
1273                                            // bed
1274                                            let bed_pos = Vec2::new(
1275                                                subplot_center.x - 4,
1276                                                subplot_center.y - room_length + 5,
1277                                            );
1278
1279                                            painter.rotated_sprite(
1280                                                bed_pos.with_z(floor_level),
1281                                                // TODO: create bed sprite specific for desert
1282                                                // houses
1283                                                SpriteKind::Bed,
1284                                                4_u8,
1285                                            );
1286
1287                                            for d in 0..2 {
1288                                                // other sprites
1289                                                let b_pos = Vec2::new(
1290                                                    subplot_center.x + 3 - (d * 7),
1291                                                    subplot_center.y - room_length
1292                                                        + 5
1293                                                        + (d * ((2 * room_length) - 9)),
1294                                                );
1295                                                painter.sprite(
1296                                                    b_pos.with_z(floor_level),
1297                                                    match (RandomField::new(0)
1298                                                        .get(b_pos.with_z(floor_level - d)))
1299                                                        % 6
1300                                                    {
1301                                                        0 => SpriteKind::TableArabicLarge,
1302                                                        1 => SpriteKind::DecorSetArabic,
1303                                                        2 => SpriteKind::DrawerSmall,
1304                                                        3 => SpriteKind::CoatRack,
1305                                                        4 => SpriteKind::TableArabicSmall,
1306                                                        _ => SpriteKind::SepareArabic,
1307                                                    },
1308                                                )
1309                                            }
1310                                        },
1311                                        _ => {
1312                                            // bath
1313                                            // wall tables with varying items
1314                                            for d in 0..2 {
1315                                                // wall tables with varying items
1316                                                let a_pos = Vec2::new(
1317                                                    subplot_center.x - room_length
1318                                                        + 1
1319                                                        + (d * ((2 * room_length) - 3)),
1320                                                    subplot_center.y,
1321                                                );
1322                                                painter.rotated_sprite(
1323                                                    a_pos.with_z(floor_level),
1324                                                    SpriteKind::WallTableArabic,
1325                                                    6 - (4 * d) as u8,
1326                                                );
1327                                                painter.owned_resource_sprite(
1328                                                    a_pos.with_z(floor_level + 1),
1329                                                    match (RandomField::new(0)
1330                                                        .get(a_pos.with_z(floor_level)))
1331                                                        % 4
1332                                                    {
1333                                                        0 => SpriteKind::Bowl,
1334                                                        1 => SpriteKind::VialEmpty,
1335                                                        2 => SpriteKind::JugArabic,
1336                                                        _ => SpriteKind::JugAndBowlArabic,
1337                                                    },
1338                                                    6 - (4 * d) as u8,
1339                                                );
1340                                                // fountain
1341                                                painter.sprite(
1342                                                    subplot_center.with_z(floor_level),
1343                                                    SpriteKind::FountainArabic,
1344                                                )
1345                                            }
1346                                        },
1347                                    }
1348                                }
1349                                // Wall Lamps
1350                                painter
1351                                    .aabb(Aabb {
1352                                        min: Vec2::new(
1353                                            subplot_center.x - 1,
1354                                            subplot_center.y - room_length + 4,
1355                                        )
1356                                        .with_z(floor_level + 4),
1357                                        max: Vec2::new(
1358                                            subplot_center.x + 1,
1359                                            subplot_center.y - room_length + 5,
1360                                        )
1361                                        .with_z(floor_level + 5),
1362                                    })
1363                                    .fill(Fill::Block(
1364                                        Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
1365                                    ));
1366                                painter
1367                                    .aabb(Aabb {
1368                                        min: Vec2::new(
1369                                            subplot_center.x - 1,
1370                                            subplot_center.y + room_length,
1371                                        )
1372                                        .with_z(floor_level + 4),
1373                                        max: Vec2::new(
1374                                            subplot_center.x + 1,
1375                                            subplot_center.y + room_length + 1,
1376                                        )
1377                                        .with_z(floor_level + 5),
1378                                    })
1379                                    .fill(Fill::Block(
1380                                        Block::air(SpriteKind::WallLampSmall).with_ori(4).unwrap(),
1381                                    ));
1382                            }
1383                        },
1384                        SubPlotKind::Library => {
1385                            // Library with stairway
1386                            let tower_length = self.diameter / 14;
1387                            let tower_height = 23;
1388                            let bldg_a_center = Vec2::new(
1389                                subplot_center.x - (2 * tower_length) + 1,
1390                                subplot_center.y,
1391                            );
1392                            let bldg_b_center =
1393                                Vec2::new(subplot_center.x + tower_length + 1, subplot_center.y);
1394                            // Library windowsills
1395                            let sq_corner = Vec2::new(
1396                                bldg_b_center.x - 3,
1397                                bldg_b_center.y - (2 * tower_length) + 1,
1398                            );
1399                            for dir in SQUARE_4 {
1400                                for h in 0..2 {
1401                                    for n in 0..2 {
1402                                        let window_sill_pos = Vec2::new(
1403                                            sq_corner.x - 1 + (dir.x * 7),
1404                                            sq_corner.y - 2 + (dir.y * ((4 * tower_length) + 1)),
1405                                        );
1406                                        painter
1407                                            .aabb(Aabb {
1408                                                min: Vec2::new(
1409                                                    window_sill_pos.x - 1,
1410                                                    window_sill_pos.y,
1411                                                )
1412                                                .with_z(
1413                                                    base + 1 + (n * (tower_height / 2)) + (h * 4),
1414                                                ),
1415                                                max: Vec2::new(
1416                                                    window_sill_pos.x + 1,
1417                                                    window_sill_pos.y + 1,
1418                                                )
1419                                                .with_z(
1420                                                    base + 2 + (n * (tower_height / 2)) + (h * 4),
1421                                                ),
1422                                            })
1423                                            .fill(wood.clone());
1424                                    }
1425                                }
1426                            }
1427                            for w in 0..2 {
1428                                for h in 0..2 {
1429                                    for n in 0..2 {
1430                                        painter
1431                                            .aabb(Aabb {
1432                                                min: Vec2::new(
1433                                                    bldg_b_center.x + (2 * tower_length),
1434                                                    bldg_b_center.y - 4 + (6 * w),
1435                                                )
1436                                                .with_z(
1437                                                    base + 1 + (n * (tower_height / 2)) + (h * 4),
1438                                                ),
1439                                                max: Vec2::new(
1440                                                    bldg_b_center.x + (2 * tower_length) + 1,
1441                                                    bldg_b_center.y - 2 + (6 * w),
1442                                                )
1443                                                .with_z(
1444                                                    base + 2 + (n * (tower_height / 2)) + (h * 4),
1445                                                ),
1446                                            })
1447                                            .fill(wood.clone());
1448                                    }
1449                                }
1450                            }
1451                            // Library
1452                            painter
1453                                .aabb(Aabb {
1454                                    min: (bldg_b_center - (2 * tower_length)).with_z(base),
1455                                    max: (bldg_b_center + (2 * tower_length))
1456                                        .with_z(base + tower_height),
1457                                })
1458                                .fill(sandstone.clone());
1459                            // Library windows
1460                            for dir in SQUARE_4 {
1461                                for h in 0..2 {
1462                                    for n in 0..2 {
1463                                        let window_pos = Vec2::new(
1464                                            sq_corner.x - 1 + (dir.x * 7),
1465                                            sq_corner.y - 1 + (dir.y * ((4 * tower_length) - 1)),
1466                                        );
1467                                        painter
1468                                            .aabb(Aabb {
1469                                                min: Vec2::new(window_pos.x - 1, window_pos.y)
1470                                                    .with_z(
1471                                                        base + 2
1472                                                            + (n * (tower_height / 2))
1473                                                            + (h * 4),
1474                                                    ),
1475                                                max: Vec2::new(window_pos.x + 1, window_pos.y + 1)
1476                                                    .with_z(
1477                                                        base + 5
1478                                                            + (n * (tower_height / 2))
1479                                                            + (h * 4),
1480                                                    ),
1481                                            })
1482                                            .fill(Fill::Block(
1483                                                Block::air(SpriteKind::WindowArabic)
1484                                                    .with_ori(2)
1485                                                    .unwrap(),
1486                                            ));
1487                                    }
1488                                }
1489                            }
1490                            for h in 0..2 {
1491                                for n in 0..2 {
1492                                    painter
1493                                        .aabb(Aabb {
1494                                            min: Vec2::new(
1495                                                bldg_b_center.x + (2 * tower_length) - 1,
1496                                                bldg_b_center.y - 4,
1497                                            )
1498                                            .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
1499                                            max: Vec2::new(
1500                                                bldg_b_center.x + (2 * tower_length),
1501                                                bldg_b_center.y - 2,
1502                                            )
1503                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1504                                        })
1505                                        .fill(Fill::Block(
1506                                            Block::air(SpriteKind::WindowArabic)
1507                                                .with_ori(4)
1508                                                .unwrap(),
1509                                        ));
1510                                    painter
1511                                        .aabb(Aabb {
1512                                            min: Vec2::new(
1513                                                bldg_b_center.x + (2 * tower_length) - 1,
1514                                                bldg_b_center.y + 2,
1515                                            )
1516                                            .with_z(base + 2 + (n * (tower_height / 2)) + (h * 4)),
1517                                            max: Vec2::new(
1518                                                bldg_b_center.x + (2 * tower_length),
1519                                                bldg_b_center.y + 4,
1520                                            )
1521                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1522                                        })
1523                                        .fill(Fill::Block(
1524                                            Block::air(SpriteKind::WindowArabic)
1525                                                .with_ori(4)
1526                                                .unwrap(),
1527                                        ));
1528                                }
1529                            }
1530                            // roof carve out
1531                            painter
1532                                .aabb(Aabb {
1533                                    min: Vec2::new(
1534                                        bldg_b_center.x - (2 * tower_length) + 2,
1535                                        bldg_b_center.y - (2 * tower_length) + 1,
1536                                    )
1537                                    .with_z(base + tower_height - 1),
1538                                    max: Vec2::new(
1539                                        bldg_b_center.x + (2 * tower_length) - 1,
1540                                        bldg_b_center.y + (2 * tower_length) - 1,
1541                                    )
1542                                    .with_z(base + tower_height),
1543                                })
1544                                .clear();
1545
1546                            // Clear Library
1547                            painter
1548                                .aabb(Aabb {
1549                                    min: (bldg_b_center - (2 * tower_length) + 1).with_z(base),
1550                                    max: (bldg_b_center + (2 * tower_length) - 1)
1551                                        .with_z(base + tower_height - 2),
1552                                })
1553                                .clear();
1554                            // Library Floor
1555                            painter
1556                                .aabb(Aabb {
1557                                    min: (bldg_b_center - (2 * tower_length))
1558                                        .with_z(base + (tower_height / 2) - 1),
1559                                    max: (bldg_b_center + (2 * tower_length))
1560                                        .with_z(base + (tower_height / 2)),
1561                                })
1562                                .fill(sandstone.clone());
1563                            // furniture
1564                            for h in 0..2 {
1565                                for dir in NEIGHBORS {
1566                                    let sprite_pos = (bldg_b_center
1567                                        + (dir * ((2 * tower_length) - 4)))
1568                                        .with_z(base + ((tower_height / 2) * h));
1569                                    painter.sprite(
1570                                        sprite_pos,
1571                                        match (RandomField::new(0).get(sprite_pos)) % 6 {
1572                                            0 => SpriteKind::DrawerSmall,
1573                                            1 => SpriteKind::ChairSingle,
1574                                            2 => SpriteKind::CoatRack,
1575                                            3 => SpriteKind::Bench,
1576                                            4 => SpriteKind::ChairDouble,
1577                                            _ => SpriteKind::TableDining,
1578                                        },
1579                                    );
1580                                }
1581
1582                                for d in 0..2 {
1583                                    for e in 0..2 {
1584                                        // bookshelfs
1585                                        let a_pos = Vec2::new(
1586                                            bldg_b_center.x - 3 + (e * 6),
1587                                            bldg_b_center.y - (2 * tower_length)
1588                                                + 1
1589                                                + (d * ((2 * (2 * tower_length)) - 3)),
1590                                        );
1591                                        painter.rotated_sprite(
1592                                            a_pos.with_z(base + 1 + ((tower_height / 2) * h)),
1593                                            SpriteKind::BookshelfArabic,
1594                                            4 - (4 * d) as u8,
1595                                        );
1596                                    }
1597                                }
1598                            }
1599                            // Library Wall Lamps
1600                            for h in 0..2 {
1601                                for n in 0..2 {
1602                                    painter
1603                                        .aabb(Aabb {
1604                                            min: Vec2::new(
1605                                                bldg_b_center.x + (2 * tower_length) - 2,
1606                                                bldg_b_center.y - 1,
1607                                            )
1608                                            .with_z(base + 4 + (n * (tower_height / 2)) + (h * 4)),
1609                                            max: Vec2::new(
1610                                                bldg_b_center.x + (2 * tower_length) - 1,
1611                                                bldg_b_center.y + 1,
1612                                            )
1613                                            .with_z(base + 5 + (n * (tower_height / 2)) + (h * 4)),
1614                                        })
1615                                        .fill(Fill::Block(
1616                                            Block::air(SpriteKind::WallLampSmall)
1617                                                .with_ori(6)
1618                                                .unwrap(),
1619                                        ));
1620                                }
1621                            }
1622                            // Library Roof Overhangs
1623                            for d in 0..2 {
1624                                painter
1625                                    .aabb(Aabb {
1626                                        min: Vec2::new(
1627                                            bldg_b_center.x - (2 * tower_length) + 1,
1628                                            bldg_b_center.y + (2 * tower_length)
1629                                                - (d * ((4 * tower_length) + 1)),
1630                                        )
1631                                        .with_z(base + tower_height - 1),
1632                                        max: Vec2::new(
1633                                            bldg_b_center.x + (2 * tower_length) - 1,
1634                                            bldg_b_center.y + (2 * tower_length) + 1
1635                                                - (d * ((4 * tower_length) + 1)),
1636                                        )
1637                                        .with_z(base + tower_height),
1638                                    })
1639                                    .fill(wood.clone());
1640                            }
1641                            painter
1642                                .aabb(Aabb {
1643                                    min: Vec2::new(
1644                                        bldg_b_center.x + (2 * tower_length),
1645                                        bldg_b_center.y - (2 * tower_length) + 1,
1646                                    )
1647                                    .with_z(base + tower_height - 1),
1648                                    max: Vec2::new(
1649                                        bldg_b_center.x + (2 * tower_length) + 1,
1650                                        bldg_b_center.y + (2 * tower_length) - 1,
1651                                    )
1652                                    .with_z(base + tower_height),
1653                                })
1654                                .fill(wood.clone());
1655                            // Stairs to Tower Top
1656                            painter
1657                                .ramp(
1658                                    Aabb {
1659                                        min: Vec2::new(
1660                                            bldg_b_center.x - (2 * tower_length) + 2,
1661                                            bldg_b_center.y - 1,
1662                                        )
1663                                        .with_z(base + tower_height - 1),
1664                                        max: Vec2::new(
1665                                            bldg_b_center.x - (2 * tower_length) + 4,
1666                                            bldg_b_center.y + 1,
1667                                        )
1668                                        .with_z(base + tower_height + 1),
1669                                    },
1670                                    Dir::NegX,
1671                                )
1672                                .fill(sandstone.clone());
1673                            // Library Top Room
1674                            painter
1675                                .aabb(Aabb {
1676                                    min: Vec2::new(
1677                                        bldg_b_center.x - tower_length + 2,
1678                                        bldg_b_center.y - tower_length,
1679                                    )
1680                                    .with_z(base + tower_height - 1),
1681                                    max: Vec2::new(
1682                                        bldg_b_center.x + tower_length + 2,
1683                                        bldg_b_center.y + tower_length,
1684                                    )
1685                                    .with_z(base + tower_height + tower_length),
1686                                })
1687                                .fill(sandstone.clone());
1688                            painter
1689                                .aabb(Aabb {
1690                                    min: Vec2::new(
1691                                        bldg_b_center.x - tower_length + 3,
1692                                        bldg_b_center.y - tower_length + 1,
1693                                    )
1694                                    .with_z(base + tower_height - 1),
1695                                    max: Vec2::new(
1696                                        bldg_b_center.x + tower_length + 1,
1697                                        bldg_b_center.y + tower_length - 1,
1698                                    )
1699                                    .with_z(base + tower_height + tower_length - 2),
1700                                })
1701                                .clear();
1702                            painter
1703                                .aabb(Aabb {
1704                                    min: Vec2::new(
1705                                        bldg_b_center.x - tower_length + 3,
1706                                        bldg_b_center.y - tower_length + 1,
1707                                    )
1708                                    .with_z(base + tower_height + tower_length - 1),
1709                                    max: Vec2::new(
1710                                        bldg_b_center.x + tower_length + 1,
1711                                        bldg_b_center.y + tower_length - 1,
1712                                    )
1713                                    .with_z(base + tower_height + tower_length),
1714                                })
1715                                .clear();
1716                            painter
1717                                .aabb(Aabb {
1718                                    min: Vec2::new(
1719                                        bldg_b_center.x + 1,
1720                                        bldg_b_center.y - tower_length - 1,
1721                                    )
1722                                    .with_z(base + tower_height - 1),
1723                                    max: Vec2::new(
1724                                        bldg_b_center.x + 3,
1725                                        bldg_b_center.y + tower_length + 1,
1726                                    )
1727                                    .with_z(base + tower_height + 2),
1728                                })
1729                                .clear();
1730                            painter
1731                                .aabb(Aabb {
1732                                    min: Vec2::new(
1733                                        bldg_b_center.x - tower_length + 1,
1734                                        bldg_b_center.y - 1,
1735                                    )
1736                                    .with_z(base + tower_height - 1),
1737                                    max: Vec2::new(
1738                                        bldg_b_center.x + tower_length + 3,
1739                                        bldg_b_center.y + 1,
1740                                    )
1741                                    .with_z(base + tower_height + 2),
1742                                })
1743                                .clear();
1744
1745                            // Library Top Room Overhangs
1746                            for d in 0..2 {
1747                                painter
1748                                    .aabb(Aabb {
1749                                        min: Vec2::new(
1750                                            bldg_b_center.x - tower_length + 3,
1751                                            bldg_b_center.y + tower_length
1752                                                - (d * ((2 * tower_length) + 1)),
1753                                        )
1754                                        .with_z(base + tower_height + tower_length - 1),
1755                                        max: Vec2::new(
1756                                            bldg_b_center.x + tower_length + 1,
1757                                            bldg_b_center.y + tower_length + 1
1758                                                - (d * ((2 * tower_length) + 1)),
1759                                        )
1760                                        .with_z(base + tower_height + tower_length),
1761                                    })
1762                                    .fill(wood.clone());
1763                            }
1764                            painter
1765                                .aabb(Aabb {
1766                                    min: Vec2::new(
1767                                        bldg_b_center.x + tower_length + 2,
1768                                        bldg_b_center.y - tower_length + 1,
1769                                    )
1770                                    .with_z(base + tower_height + tower_length - 1),
1771                                    max: Vec2::new(
1772                                        bldg_b_center.x + tower_length + 3,
1773                                        bldg_b_center.y + tower_length - 1,
1774                                    )
1775                                    .with_z(base + tower_height + tower_length),
1776                                })
1777                                .fill(wood.clone());
1778                            // Library Top Room Roof Ornament
1779                            painter
1780                                .aabb(Aabb {
1781                                    min: Vec2::new(
1782                                        bldg_b_center.x + tower_length + 1,
1783                                        bldg_b_center.y - tower_length,
1784                                    )
1785                                    .with_z(base + tower_height + tower_length),
1786                                    max: Vec2::new(
1787                                        bldg_b_center.x + tower_length + 2,
1788                                        bldg_b_center.y + tower_length,
1789                                    )
1790                                    .with_z(base + tower_height + tower_length + 2),
1791                                })
1792                                .fill(sandstone.clone());
1793                            painter
1794                                .aabb(Aabb {
1795                                    min: Vec2::new(
1796                                        bldg_b_center.x + tower_length + 1,
1797                                        bldg_b_center.y - tower_length + 2,
1798                                    )
1799                                    .with_z(base + tower_height + tower_length + 2),
1800                                    max: Vec2::new(
1801                                        bldg_b_center.x + tower_length + 2,
1802                                        bldg_b_center.y + tower_length - 2,
1803                                    )
1804                                    .with_z(base + tower_height + tower_length + 3),
1805                                })
1806                                .fill(sandstone.clone());
1807                            painter
1808                                .aabb(Aabb {
1809                                    min: Vec2::new(
1810                                        bldg_b_center.x + tower_length + 1,
1811                                        bldg_b_center.y - 1,
1812                                    )
1813                                    .with_z(base + tower_height + tower_length + 3),
1814                                    max: Vec2::new(
1815                                        bldg_b_center.x + tower_length + 2,
1816                                        bldg_b_center.y + 1,
1817                                    )
1818                                    .with_z(base + tower_height + tower_length + 4),
1819                                })
1820                                .fill(sandstone.clone());
1821                            // Stairway Tower windowsills
1822                            for h in 0..2 {
1823                                painter
1824                                    .aabb(Aabb {
1825                                        min: Vec2::new(
1826                                            bldg_a_center.x - 1,
1827                                            bldg_a_center.y - tower_length - 1,
1828                                        )
1829                                        .with_z(base + (tower_height / 2) - 4 + (h * 6)),
1830                                        max: Vec2::new(
1831                                            bldg_a_center.x + 1,
1832                                            bldg_a_center.y + tower_length + 1,
1833                                        )
1834                                        .with_z(base + (tower_height / 2) - 3 + (h * 6)),
1835                                    })
1836                                    .fill(wood.clone());
1837                            }
1838                            // Stairway Tower base
1839                            painter
1840                                .aabb(Aabb {
1841                                    min: (bldg_a_center - tower_length - 1).with_z(base),
1842                                    max: (bldg_a_center + tower_length + 1).with_z(base + 6),
1843                                })
1844                                .fill(sandstone.clone());
1845                            // Tower
1846                            painter
1847                                .aabb(Aabb {
1848                                    min: (bldg_a_center - tower_length).with_z(base),
1849                                    max: (bldg_a_center + tower_length).with_z(base + tower_height),
1850                                })
1851                                .fill(sandstone.clone());
1852                            // Stairway Tower windows
1853                            for h in 0..2 {
1854                                painter
1855                                    .aabb(Aabb {
1856                                        min: Vec2::new(
1857                                            bldg_a_center.x - 1,
1858                                            bldg_a_center.y - tower_length,
1859                                        )
1860                                        .with_z(base + (tower_height / 2) - 3 + (h * 6)),
1861                                        max: Vec2::new(
1862                                            bldg_a_center.x + 1,
1863                                            bldg_a_center.y + tower_length,
1864                                        )
1865                                        .with_z(base + (tower_height / 2) + (h * 6)),
1866                                    })
1867                                    .fill(Fill::Block(
1868                                        Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
1869                                    ));
1870                            }
1871                            // Stairway Tower entry
1872                            painter
1873                                .aabb(Aabb {
1874                                    min: Vec2::new(
1875                                        bldg_a_center.x - 2,
1876                                        bldg_a_center.y - tower_length - 2,
1877                                    )
1878                                    .with_z(base),
1879                                    max: Vec2::new(
1880                                        bldg_a_center.x + 2,
1881                                        bldg_a_center.y + tower_length + 2,
1882                                    )
1883                                    .with_z(base + 5),
1884                                })
1885                                .fill(sandstone.clone());
1886                            // clear Stairway Tower entry
1887                            painter
1888                                .aabb(Aabb {
1889                                    min: Vec2::new(
1890                                        bldg_a_center.x - 1,
1891                                        bldg_a_center.y - tower_length - 5,
1892                                    )
1893                                    .with_z(base),
1894                                    max: Vec2::new(
1895                                        bldg_a_center.x + 1,
1896                                        bldg_a_center.y + tower_length + 5,
1897                                    )
1898                                    .with_z(base + 4),
1899                                })
1900                                .clear();
1901                            // clear Stairway Tower base
1902                            painter
1903                                .aabb(Aabb {
1904                                    min: (bldg_a_center - tower_length).with_z(base),
1905                                    max: (bldg_a_center + tower_length).with_z(base + 6),
1906                                })
1907                                .clear();
1908                            // Stairway Tower Entry Lamps
1909                            for d in 0..2 {
1910                                painter
1911                                    .aabb(Aabb {
1912                                        min: Vec2::new(
1913                                            bldg_a_center.x - 1,
1914                                            bldg_a_center.y - tower_length - 3
1915                                                + (d * ((2 * tower_length) + 6)),
1916                                        )
1917                                        .with_z(base + 4),
1918                                        max: Vec2::new(
1919                                            bldg_a_center.x + 1,
1920                                            bldg_a_center.y - tower_length - 2
1921                                                + (d * ((2 * tower_length) + 4)),
1922                                        )
1923                                        .with_z(base + 5),
1924                                    })
1925                                    .fill(Fill::Block(
1926                                        Block::air(SpriteKind::WallLampSmall)
1927                                            .with_ori(0 + (4 * d) as u8)
1928                                            .unwrap(),
1929                                    ));
1930                            }
1931                            // Library entries from Stairway Tower
1932                            for h in 0..2 {
1933                                painter
1934                                    .aabb(Aabb {
1935                                        min: Vec2::new(
1936                                            bldg_a_center.x + tower_length - 1,
1937                                            bldg_a_center.y - 1,
1938                                        )
1939                                        .with_z(base + (h * (tower_height / 2))),
1940                                        max: Vec2::new(
1941                                            bldg_a_center.x + tower_length + 1,
1942                                            bldg_a_center.y + 1,
1943                                        )
1944                                        .with_z(base + (h * (tower_height / 2)) + 3),
1945                                    })
1946                                    .clear();
1947                            }
1948                            // Stairway Tower Platform
1949                            painter
1950                                .aabb(Aabb {
1951                                    min: (bldg_a_center - tower_length - 2)
1952                                        .with_z(base + tower_height),
1953                                    max: (bldg_a_center + tower_length + 2)
1954                                        .with_z(base + tower_height + 3),
1955                                })
1956                                .fill(sandstone.clone());
1957
1958                            painter
1959                                .aabb(Aabb {
1960                                    min: (bldg_a_center - tower_length - 1)
1961                                        .with_z(base + tower_height + 2),
1962                                    max: (bldg_a_center + tower_length + 1)
1963                                        .with_z(base + tower_height + 3),
1964                                })
1965                                .clear();
1966
1967                            painter
1968                                .aabb(Aabb {
1969                                    min: Vec2::new(
1970                                        bldg_a_center.x + tower_length + 1,
1971                                        bldg_a_center.y - 1,
1972                                    )
1973                                    .with_z(base + tower_height + 2),
1974                                    max: Vec2::new(
1975                                        bldg_a_center.x + tower_length + 2,
1976                                        bldg_a_center.y + 1,
1977                                    )
1978                                    .with_z(base + tower_height + 3),
1979                                })
1980                                .clear();
1981                            // clear Tower
1982                            let tower_clear = painter.aabb(Aabb {
1983                                min: (bldg_a_center - tower_length + 1).with_z(base),
1984                                max: (bldg_a_center + tower_length - 1)
1985                                    .with_z(base + tower_height + 3),
1986                            });
1987                            tower_clear.clear();
1988                            // stairway
1989                            let stair_radius = tower_length + 1;
1990                            let stairs_clear = painter.aabb(Aabb {
1991                                min: (bldg_a_center - stair_radius).with_z(base),
1992                                max: (bldg_a_center + stair_radius).with_z(base + tower_height + 2),
1993                            });
1994                            stairs_clear
1995                                .sample(spiral_staircase(
1996                                    bldg_a_center.with_z(base + tower_height + 2),
1997                                    stair_radius as f32,
1998                                    0.5,
1999                                    ((2 * tower_length) - 1) as f32,
2000                                ))
2001                                .intersect(tower_clear)
2002                                .fill(sandstone.clone());
2003                        },
2004                        SubPlotKind::WatchTower(tower) => {
2005                            // WatchTower Windowsills
2006                            for h in 0..4 {
2007                                painter
2008                                    .aabb(Aabb {
2009                                        min: Vec2::new(
2010                                            subplot_center.x - 1,
2011                                            subplot_center.y - tower.length - 1,
2012                                        )
2013                                        .with_z(base + 8 + (h * (tower.height / 5))),
2014                                        max: Vec2::new(
2015                                            subplot_center.x + 1,
2016                                            subplot_center.y + tower.length + 1,
2017                                        )
2018                                        .with_z(base + 9 + (h * (tower.height / 5))),
2019                                    })
2020                                    .fill(wood.clone());
2021                            }
2022                            for h in 0..4 {
2023                                painter
2024                                    .aabb(Aabb {
2025                                        min: Vec2::new(
2026                                            subplot_center.x - tower.length - 1,
2027                                            subplot_center.y - 1,
2028                                        )
2029                                        .with_z(base + 8 + (h * (tower.height / 5))),
2030                                        max: Vec2::new(
2031                                            subplot_center.x + tower.length + 1,
2032                                            subplot_center.y + 1,
2033                                        )
2034                                        .with_z(base + 9 + (h * (tower.height / 5))),
2035                                    })
2036                                    .fill(wood.clone());
2037                            }
2038                            // Watch Tower base
2039                            painter
2040                                .aabb(Aabb {
2041                                    min: (subplot_center - tower.length - 1).with_z(base),
2042                                    max: (subplot_center + tower.length + 1).with_z(base + 6),
2043                                })
2044                                .fill(sandstone.clone());
2045                            // WatchTower
2046                            painter
2047                                .aabb(Aabb {
2048                                    min: (subplot_center - tower.length).with_z(base),
2049                                    max: (subplot_center + tower.length)
2050                                        .with_z(base + tower.height),
2051                                })
2052                                .fill(sandstone.clone());
2053                            // WatchTower Windows
2054                            for h in 0..4 {
2055                                painter
2056                                    .aabb(Aabb {
2057                                        min: Vec2::new(
2058                                            subplot_center.x - 1,
2059                                            subplot_center.y - tower.length,
2060                                        )
2061                                        .with_z(base + 9 + (h * (tower.height / 5))),
2062                                        max: Vec2::new(
2063                                            subplot_center.x + 1,
2064                                            subplot_center.y + tower.length,
2065                                        )
2066                                        .with_z(base + 12 + (h * (tower.height / 5))),
2067                                    })
2068                                    .fill(Fill::Block(
2069                                        Block::air(SpriteKind::WindowArabic).with_ori(2).unwrap(),
2070                                    ));
2071                            }
2072                            for h in 0..4 {
2073                                painter
2074                                    .aabb(Aabb {
2075                                        min: Vec2::new(
2076                                            subplot_center.x - tower.length,
2077                                            subplot_center.y - 1,
2078                                        )
2079                                        .with_z(base + 9 + (h * (tower.height / 5))),
2080                                        max: Vec2::new(
2081                                            subplot_center.x + tower.length,
2082                                            subplot_center.y + 1,
2083                                        )
2084                                        .with_z(base + 12 + (h * (tower.height / 5))),
2085                                    })
2086                                    .fill(Fill::Block(
2087                                        Block::air(SpriteKind::WindowArabic).with_ori(4).unwrap(),
2088                                    ));
2089                            }
2090                            // Watch Tower entries
2091                            painter
2092                                .aabb(Aabb {
2093                                    min: Vec2::new(
2094                                        subplot_center.x - 2,
2095                                        subplot_center.y - tower.length - 2,
2096                                    )
2097                                    .with_z(base),
2098                                    max: Vec2::new(
2099                                        subplot_center.x + 2,
2100                                        subplot_center.y + tower.length + 2,
2101                                    )
2102                                    .with_z(base + 5),
2103                                })
2104                                .fill(sandstone.clone());
2105                            painter
2106                                .aabb(Aabb {
2107                                    min: Vec2::new(
2108                                        subplot_center.x - 1,
2109                                        subplot_center.y - tower.length - 2,
2110                                    )
2111                                    .with_z(base),
2112                                    max: Vec2::new(
2113                                        subplot_center.x + 1,
2114                                        subplot_center.y + tower.length + 2,
2115                                    )
2116                                    .with_z(base + 4),
2117                                })
2118                                .clear();
2119                            // clear Watch Tower base
2120                            painter
2121                                .aabb(Aabb {
2122                                    min: (subplot_center - tower.length).with_z(base),
2123                                    max: (subplot_center + tower.length).with_z(base + 5),
2124                                })
2125                                .clear();
2126                            // WatchTower Entry Lamps
2127                            for d in 0..2 {
2128                                painter
2129                                    .aabb(Aabb {
2130                                        min: Vec2::new(
2131                                            subplot_center.x - 1,
2132                                            subplot_center.y - tower.length - 3
2133                                                + (d * ((2 * tower.length) + 6)),
2134                                        )
2135                                        .with_z(base + 4),
2136                                        max: Vec2::new(
2137                                            subplot_center.x + 1,
2138                                            subplot_center.y - tower.length - 2
2139                                                + (d * ((2 * tower.length) + 4)),
2140                                        )
2141                                        .with_z(base + 5),
2142                                    })
2143                                    .fill(Fill::Block(
2144                                        Block::air(SpriteKind::WallLampSmall)
2145                                            .with_ori(0 + (4 * d) as u8)
2146                                            .unwrap(),
2147                                    ));
2148                            }
2149                            // Watchtower Platform
2150                            painter
2151                                .aabb(Aabb {
2152                                    min: (subplot_center - tower.length - 2)
2153                                        .with_z(base + tower.height),
2154                                    max: (subplot_center + tower.length + 2)
2155                                        .with_z(base + tower.height + 4),
2156                                })
2157                                .fill(sandstone.clone());
2158
2159                            painter
2160                                .aabb(Aabb {
2161                                    min: (subplot_center - tower.length - 1)
2162                                        .with_z(base + tower.height + 2),
2163                                    max: (subplot_center + tower.length + 1)
2164                                        .with_z(base + tower.height + 4),
2165                                })
2166                                .clear();
2167
2168                            painter
2169                                .aabb(Aabb {
2170                                    min: Vec2::new(
2171                                        subplot_center.x - tower.length - 2,
2172                                        subplot_center.y - 2,
2173                                    )
2174                                    .with_z(base + tower.height + 3),
2175                                    max: Vec2::new(
2176                                        subplot_center.x + tower.length + 2,
2177                                        subplot_center.y + 2,
2178                                    )
2179                                    .with_z(base + tower.height + 4),
2180                                })
2181                                .clear();
2182                            painter
2183                                .aabb(Aabb {
2184                                    min: Vec2::new(
2185                                        subplot_center.x - 2,
2186                                        subplot_center.y - tower.length - 2,
2187                                    )
2188                                    .with_z(base + tower.height + 3),
2189                                    max: Vec2::new(
2190                                        subplot_center.x + 2,
2191                                        subplot_center.y + tower.length + 2,
2192                                    )
2193                                    .with_z(base + tower.height + 4),
2194                                })
2195                                .clear();
2196
2197                            // clear Tower
2198                            let tower_clear = painter.aabb(Aabb {
2199                                min: (subplot_center - tower.length + 1).with_z(base),
2200                                max: (subplot_center + tower.length - 1)
2201                                    .with_z(base + tower.height + 3),
2202                            });
2203                            tower_clear.clear();
2204                            // stairway
2205                            let stair_radius = tower.length + 1;
2206                            let stairs_clear = painter.aabb(Aabb {
2207                                min: (subplot_center - stair_radius).with_z(base),
2208                                max: (subplot_center + stair_radius)
2209                                    .with_z(base + tower.height + 2),
2210                            });
2211                            stairs_clear
2212                                .sample(spiral_staircase(
2213                                    subplot_center.with_z(base + tower.height + 2),
2214                                    stair_radius as f32,
2215                                    0.5,
2216                                    (2 * tower.length) as f32,
2217                                ))
2218                                .intersect(tower_clear)
2219                                .fill(sandstone.clone());
2220                        },
2221                        SubPlotKind::AnimalShed => {
2222                            // fenced animal shed
2223                            let shed_length = self.diameter / 14;
2224                            // small fence
2225                            painter
2226                                .aabb(Aabb {
2227                                    min: Vec2::new(
2228                                        subplot_center.x - (2 * shed_length),
2229                                        subplot_center.y - (2 * shed_length) - 1,
2230                                    )
2231                                    .with_z(base),
2232                                    max: Vec2::new(
2233                                        subplot_center.x - (2 * shed_length) + 1,
2234                                        subplot_center.y + (2 * shed_length) + 1,
2235                                    )
2236                                    .with_z(base + 2),
2237                                })
2238                                .union(
2239                                    painter.aabb(Aabb {
2240                                        min: Vec2::new(
2241                                            subplot_center.x + (2 * shed_length) + 1,
2242                                            subplot_center.y - (2 * shed_length) - 1,
2243                                        )
2244                                        .with_z(base),
2245                                        max: Vec2::new(
2246                                            subplot_center.x + (2 * shed_length) + 2,
2247                                            subplot_center.y + (2 * shed_length) + 1,
2248                                        )
2249                                        .with_z(base + 2),
2250                                    }),
2251                                )
2252                                .union(
2253                                    painter.aabb(Aabb {
2254                                        min: Vec2::new(
2255                                            subplot_center.x - (2 * shed_length),
2256                                            subplot_center.y - (2 * shed_length) - 1,
2257                                        )
2258                                        .with_z(base),
2259                                        max: Vec2::new(
2260                                            subplot_center.x + (2 * shed_length) + 2,
2261                                            subplot_center.y - (2 * shed_length),
2262                                        )
2263                                        .with_z(base + 2),
2264                                    }),
2265                                )
2266                                .union(
2267                                    painter.aabb(Aabb {
2268                                        min: Vec2::new(
2269                                            subplot_center.x - (2 * shed_length),
2270                                            subplot_center.y + (2 * shed_length),
2271                                        )
2272                                        .with_z(base),
2273                                        max: Vec2::new(
2274                                            subplot_center.x + (2 * shed_length) + 2,
2275                                            subplot_center.y + (2 * shed_length) + 1,
2276                                        )
2277                                        .with_z(base + 2),
2278                                    }),
2279                                )
2280                                .fill(sandstone_broken.clone());
2281                            // shed
2282                            painter
2283                                .aabb(Aabb {
2284                                    min: Vec2::new(
2285                                        subplot_center.x - shed_length + 2,
2286                                        subplot_center.y - shed_length,
2287                                    )
2288                                    .with_z(base),
2289                                    max: Vec2::new(
2290                                        subplot_center.x + shed_length + 2,
2291                                        subplot_center.y + shed_length,
2292                                    )
2293                                    .with_z(base + shed_length + 1),
2294                                })
2295                                .fill(sandstone.clone());
2296                            painter
2297                                .aabb(Aabb {
2298                                    min: Vec2::new(
2299                                        subplot_center.x - shed_length + 3,
2300                                        subplot_center.y - shed_length + 1,
2301                                    )
2302                                    .with_z(base),
2303                                    max: Vec2::new(
2304                                        subplot_center.x + shed_length + 1,
2305                                        subplot_center.y + shed_length - 1,
2306                                    )
2307                                    .with_z(base + shed_length - 1),
2308                                })
2309                                .clear();
2310                            painter
2311                                .aabb(Aabb {
2312                                    min: Vec2::new(
2313                                        subplot_center.x - shed_length + 3,
2314                                        subplot_center.y - shed_length + 1,
2315                                    )
2316                                    .with_z(base + shed_length),
2317                                    max: Vec2::new(
2318                                        subplot_center.x + shed_length + 1,
2319                                        subplot_center.y + shed_length - 1,
2320                                    )
2321                                    .with_z(base + shed_length + 1),
2322                                })
2323                                .clear();
2324                            painter
2325                                .aabb(Aabb {
2326                                    min: Vec2::new(
2327                                        subplot_center.x + 1,
2328                                        subplot_center.y - shed_length - 1,
2329                                    )
2330                                    .with_z(base),
2331                                    max: Vec2::new(
2332                                        subplot_center.x + 3,
2333                                        subplot_center.y + shed_length + 1,
2334                                    )
2335                                    .with_z(base + 3),
2336                                })
2337                                .clear();
2338                            painter
2339                                .aabb(Aabb {
2340                                    min: Vec2::new(
2341                                        subplot_center.x - shed_length + 1,
2342                                        subplot_center.y - 1,
2343                                    )
2344                                    .with_z(base),
2345                                    max: Vec2::new(
2346                                        subplot_center.x + shed_length + 3,
2347                                        subplot_center.y + 1,
2348                                    )
2349                                    .with_z(base + 3),
2350                                })
2351                                .clear();
2352                            // Shed Overhangs
2353                            for d in 0..2 {
2354                                painter
2355                                    .aabb(Aabb {
2356                                        min: Vec2::new(
2357                                            subplot_center.x - shed_length + 3,
2358                                            subplot_center.y + shed_length
2359                                                - (d * ((2 * shed_length) + 1)),
2360                                        )
2361                                        .with_z(base + shed_length - 1),
2362                                        max: Vec2::new(
2363                                            subplot_center.x + shed_length + 1,
2364                                            subplot_center.y + shed_length + 1
2365                                                - (d * ((2 * shed_length) + 1)),
2366                                        )
2367                                        .with_z(base + shed_length),
2368                                    })
2369                                    .fill(wood.clone());
2370                            }
2371                            painter
2372                                .aabb(Aabb {
2373                                    min: Vec2::new(
2374                                        subplot_center.x + shed_length + 2,
2375                                        subplot_center.y - shed_length + 1,
2376                                    )
2377                                    .with_z(base + shed_length - 1),
2378                                    max: Vec2::new(
2379                                        subplot_center.x + shed_length + 3,
2380                                        subplot_center.y + shed_length - 1,
2381                                    )
2382                                    .with_z(base + shed_length),
2383                                })
2384                                .fill(wood.clone());
2385                            // Shed Roof Ornament
2386                            painter
2387                                .aabb(Aabb {
2388                                    min: Vec2::new(
2389                                        subplot_center.x + shed_length + 1,
2390                                        subplot_center.y - shed_length,
2391                                    )
2392                                    .with_z(base + shed_length),
2393                                    max: Vec2::new(
2394                                        subplot_center.x + shed_length + 2,
2395                                        subplot_center.y + shed_length,
2396                                    )
2397                                    .with_z(base + shed_length + 2),
2398                                })
2399                                .fill(sandstone.clone());
2400                            painter
2401                                .aabb(Aabb {
2402                                    min: Vec2::new(
2403                                        subplot_center.x + shed_length + 1,
2404                                        subplot_center.y - shed_length + 2,
2405                                    )
2406                                    .with_z(base + shed_length + 2),
2407                                    max: Vec2::new(
2408                                        subplot_center.x + shed_length + 2,
2409                                        subplot_center.y + shed_length - 2,
2410                                    )
2411                                    .with_z(base + shed_length + 3),
2412                                })
2413                                .fill(sandstone.clone());
2414                            painter
2415                                .aabb(Aabb {
2416                                    min: Vec2::new(
2417                                        subplot_center.x + shed_length + 1,
2418                                        subplot_center.y - 1,
2419                                    )
2420                                    .with_z(base + shed_length + 3),
2421                                    max: Vec2::new(
2422                                        subplot_center.x + shed_length + 2,
2423                                        subplot_center.y + 1,
2424                                    )
2425                                    .with_z(base + shed_length + 4),
2426                                })
2427                                .fill(sandstone.clone());
2428                        },
2429                        SubPlotKind::PalmTree => {
2430                            // Palm
2431                            painter
2432                                .cylinder(Aabb {
2433                                    min: (subplot_center - 8).with_z(base),
2434                                    max: (subplot_center + 14).with_z(base + 1),
2435                                })
2436                                .fill(sandstone.clone());
2437                            painter
2438                                .cylinder(Aabb {
2439                                    min: (subplot_center - 7).with_z(base),
2440                                    max: (subplot_center + 13).with_z(base + 1),
2441                                })
2442                                .fill(Fill::Brick(BlockKind::Rock, Rgb::new(235, 178, 99), 12));
2443                            for p in 0..2 {
2444                                let palm_pos = (subplot_center + 3 + (2 * p)).with_z(base);
2445                                lazy_static! {
2446                                    pub static ref PALM: AssetHandle<StructuresGroup> =
2447                                        PrefabStructure::load_group("trees.palms");
2448                                }
2449                                let rng = RandomField::new(0).get(palm_pos) % 10;
2450                                let palm = PALM.read();
2451                                let palm = palm[rng as usize % palm.len()].clone();
2452                                painter
2453                                    .prim(Primitive::Prefab(Box::new(palm.clone())))
2454                                    .translate(palm_pos)
2455                                    .fill(Fill::Prefab(Box::new(palm), palm_pos, rng));
2456                            }
2457                        },
2458                    }
2459                }
2460                // spawn campfire in some multiplots that are not markethall
2461                let campfire_pos = (center).with_z(base + 1);
2462                if self.campfire {
2463                    painter.spawn(
2464                        EntityInfo::at(campfire_pos.map(|e| e as f32))
2465                            .into_special(SpecialEntity::Waypoint),
2466                    )
2467                }
2468            },
2469        }
2470    }
2471}