diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs
index 173aa7d1f7..d10478e5f7 100644
--- a/world/src/block/mod.rs
+++ b/world/src/block/mod.rs
@@ -66,15 +66,19 @@ impl<'a> BlockGen<'a> {
                     // Conservative range of radius: [8, 47]
                     let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8;
 
-                    max_height.max(
-                        if cliff_pos.map(|e| e as f32).distance_squared(wpos)
-                            < (radius as f32 + tolerance).powf(2.0)
-                        {
-                            cliff_sample.alt + height * (1.0 - cliff_sample.chaos) + cliff_hill
-                        } else {
-                            0.0
-                        },
-                    )
+                    if cliff_sample.water_dist.map(|d| d > radius as f32).unwrap_or(true) {
+                        max_height.max(
+                            if cliff_pos.map(|e| e as f32).distance_squared(wpos)
+                                < (radius as f32 + tolerance).powf(2.0)
+                            {
+                                cliff_sample.alt + height * (1.0 - cliff_sample.chaos) + cliff_hill
+                            } else {
+                                0.0
+                            },
+                        )
+                    } else {
+                        max_height
+                    }
                 },
                 _ => max_height,
             },
diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs
index 0f285fef28..ecd223dfd8 100644
--- a/world/src/block/natural.rs
+++ b/world/src/block/natural.rs
@@ -28,6 +28,7 @@ pub fn structure_gen<'a>(
     if (st_sample.tree_density as f64) < random_seed
         || st_sample.alt < st_sample.water_level
         || st_sample.spawn_rate < 0.5
+        || st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false)
     {
         return None;
     }
diff --git a/world/src/civ/mod.rs b/world/src/civ/mod.rs
index edf842d98e..b693f5a41a 100644
--- a/world/src/civ/mod.rs
+++ b/world/src/civ/mod.rs
@@ -95,9 +95,11 @@ impl Civs {
             let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32);
 
             // Flatten ground
-            let flatten_radius = 12.0;
+            let flatten_radius = 10.0;
             if let Some(center_alt) = ctx.sim.get_alt_approx(wpos) {
-                for pos in Spiral2d::new().map(|offs| site.center + offs).take(radius.pow(2) as usize) {
+                for offs in Spiral2d::new().take(radius.pow(2) as usize) {
+                    let center_alt = center_alt + if offs.magnitude_squared() <= 6i32.pow(2) { 16.0 } else { 0.0 }; // Raise the town centre up a little
+                    let pos = site.center + offs;
                     let factor = (1.0 - (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius) * 1.15;
                     ctx.sim
                         .get_mut(pos)
diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs
index 97a2c9108c..6de86303b8 100644
--- a/world/src/column/mod.rs
+++ b/world/src/column/mod.rs
@@ -679,7 +679,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
                                             Some((river_dist - river_width * 0.5) as f32),
                                             alt_for_river.min(lake_water_alt - 1.0 - river_gouge),
                                             lake_water_alt - river_gouge,
-                                            alt_for_river.min(lake_water_alt - 1.0),
+                                            alt_for_river.max(lake_water_alt),
                                             0.0,
                                         ));
                                     }
@@ -753,7 +753,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
                                             Some(lake_dist as f32),
                                             alt_for_river.min(lake_water_alt - 1.0 - river_gouge),
                                             lake_water_alt - river_gouge,
-                                            alt_for_river.min(lake_water_alt - 1.0),
+                                            alt_for_river.max(lake_water_alt),
                                             0.0,
                                         ));
                                     }
@@ -774,7 +774,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
                                                 alt.min(lake_water_alt - 1.0 - river_gouge),
                                                 downhill_water_alt.max(lake_water_alt)
                                                     - river_gouge,
-                                                alt.min(lake_water_alt - 1.0),
+                                                alt.max(lake_water_alt),
                                                 0.0,
                                             ));
                                         } else {
diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs
index 7c0ac61f25..dab24656ea 100644
--- a/world/src/sim/mod.rs
+++ b/world/src/sim/mod.rs
@@ -1867,7 +1867,8 @@ impl SimChunk {
             )
         };
 
-        let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2;
+        //let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2;
+        let cliff = 0.0; // Disable cliffs
 
         // Logistic regression.  Make sure x ∈ (0, 1).
         let logit = |x: f64| x.ln() - x.neg().ln_1p();
diff --git a/world/src/site/settlement/building/archetype/house.rs b/world/src/site/settlement/building/archetype/house.rs
index 25040f44d4..25101a4abd 100644
--- a/world/src/site/settlement/building/archetype/house.rs
+++ b/world/src/site/settlement/building/archetype/house.rs
@@ -11,6 +11,20 @@ use super::{
     super::skeleton::*,
 };
 
+const COLOR_THEMES: [Rgb<u8>; 11] = [
+    Rgb::new(0x1D, 0x4D, 0x45),
+    Rgb::new(0xB3, 0x7D, 0x60),
+    Rgb::new(0xAC, 0x5D, 0x26),
+    Rgb::new(0x32, 0x46, 0x6B),
+    Rgb::new(0x2B, 0x19, 0x0F),
+    Rgb::new(0x93, 0x78, 0x51),
+    Rgb::new(0x92, 0x57, 0x24),
+    Rgb::new(0x4A, 0x4E, 0x4E),
+    Rgb::new(0x2F, 0x32, 0x47),
+    Rgb::new(0x8F, 0x35, 0x43),
+    Rgb::new(0x6D, 0x1E, 0x3A),
+];
+
 pub struct House {
     roof_color: Rgb<u8>,
     noise: RandomField,
@@ -116,11 +130,10 @@ impl Archetype for House {
         };
 
         let this = Self {
-            roof_color: Rgb::new(
-                rng.gen_range(50, 200),
-                rng.gen_range(50, 200),
-                rng.gen_range(50, 200),
-            ),
+            roof_color: COLOR_THEMES
+                .choose(rng)
+                .unwrap()
+                .map(|e| e.saturating_add(rng.gen_range(0, 20)) - 10),
             noise: RandomField::new(rng.gen()),
             roof_ribbing: rng.gen(),
             roof_ribbing_diagonal: rng.gen(),
@@ -141,7 +154,7 @@ impl Archetype for House {
 
         let make_block = |r, g, b| {
             let nz = self.noise.get(Vec3::new(center_offset.x, center_offset.y, z * 8));
-            BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b) + (nz & 0x0F) as u8 - 8), 2)
+            BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b).map(|e: u8| e.saturating_add((nz & 0x0F) as u8).saturating_sub(8))), 2)
         };
 
         let facade_layer = 3;
diff --git a/world/src/site/settlement/mod.rs b/world/src/site/settlement/mod.rs
index c2174e6fc9..002253bd88 100644
--- a/world/src/site/settlement/mod.rs
+++ b/world/src/site/settlement/mod.rs
@@ -251,7 +251,7 @@ impl Settlement {
     }
 
     pub fn place_town(&mut self, ctx: &mut GenCtx<impl Rng>) {
-        const PLOT_COUNT: usize = 2;
+        const PLOT_COUNT: usize = 3;
 
         let mut origin = Vec2::new(ctx.rng.gen_range(-2, 3), ctx.rng.gen_range(-2, 3));
 
@@ -273,6 +273,7 @@ impl Settlement {
         }
 
         // Boundary wall
+        /*
         let spokes = CARDINALS
             .iter()
             .filter_map(|dir| {
@@ -316,6 +317,7 @@ impl Settlement {
         }
         self.land
             .write_path(&wall_path, WayKind::Wall, buildable, true);
+        */
     }
 
     pub fn place_buildings(&mut self, ctx: &mut GenCtx<impl Rng>) {
@@ -326,10 +328,11 @@ impl Settlement {
         };
 
         for tile in Spiral2d::new().map(|offs| town_center + offs).take(16usize.pow(2)) {
-            for _ in 0..ctx.rng.gen_range(1, 5) {
-                for _ in 0..10 {
+            // This is a stupid way to decide how to place buildings
+            for _ in 0..ctx.rng.gen_range(2, 5) {
+                for _ in 0..25 {
                     let house_pos = tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
-                        + Vec2::<i32>::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32) / 2);
+                        + Vec2::<i32>::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32 / 2));
 
                     let tile_pos = house_pos.map(|e| e.div_euclid(AREA_SIZE as i32));
                     if !matches!(self.land.plot_at(tile_pos), Some(Plot::Town))
@@ -481,20 +484,23 @@ impl Settlement {
 
                     // Try to use the column at the centre of the path for sampling to make them flatter
                     let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos)).unwrap_or(col_sample);
-                    let bridge_offset = if let Some(water_dist) = col.water_dist {
-                        ((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0
+                    let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist {
+                        (
+                            ((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
+                            ((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs()) * (col.riverless_alt + 5.0 - col.alt).max(0.0) * 1.75 + 3.0) as i32,
+                        )
                     } else {
-                        0.0
+                        (0.0, 3)
                     };
                     let surface_z = (col.riverless_alt + bridge_offset).floor() as i32;
 
-                    for z in inset - 3..inset {
+                    for z in inset - depth..inset {
                         vol.set(
                             Vec3::new(offs.x, offs.y, surface_z + z),
-                            if bridge_offset >= 2.0 {
+                            if bridge_offset >= 2.0 && dist >= 2.5 || z < inset - 1 {
                                 Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
                             } else {
-                                Block::new(BlockKind::Normal, noisy_color(Rgb::new(90, 70, 50), 8))
+                                Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8))
                             },
                         );
                     }
@@ -622,7 +628,10 @@ impl Settlement {
             Some(Plot::Dirt) => return Some(Rgb::new(90, 70, 50)),
             Some(Plot::Grass) => return Some(Rgb::new(100, 200, 0)),
             Some(Plot::Water) => return Some(Rgb::new(100, 150, 250)),
-            Some(Plot::Town) => return Some(Rgb::new(130, 120, 80)),
+            Some(Plot::Town) => return Some(Rgb::new(150, 110, 60)
+                .map2(Rgb::iota(), |e: u8, i: i32| e
+                    .saturating_add((self.noise.get(Vec3::new(pos.x, pos.y, i * 5)) % 16) as u8)
+                    .saturating_sub(8))),
             Some(Plot::Field { seed, .. }) => {
                 let furrow_dirs = [
                     Vec2::new(1, 0),
@@ -760,7 +769,9 @@ impl Land {
                 let proj_point = line.projected_point(pos.map(|e| e as f32));
                 let dist = proj_point.distance(pos.map(|e| e as f32));
                 if dist < way.width() {
-                    sample.way = Some((way, dist, proj_point));
+                    sample.way = sample.way
+                        .filter(|(_, d, _)| *d < dist)
+                        .or(Some((way, dist, proj_point)));
                 }
             }
         }