diff --git a/src/config.rs b/src/config.rs
index 3bfc207..6a3291e 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -44,6 +44,9 @@ pub struct GenerationConfig {
     /// (min, max) distance between platforms
     pub platform_distance_bounds: (usize, usize),
 
+    /// probability for doing the last shift direction again
+    pub momentum_prob: f32,
+
     // ------- TODO: these should go somewhere else -----
     pub waypoints: Vec<Position>,
 }
@@ -99,6 +102,7 @@ impl Default for GenerationConfig {
             ],
             step_weights: vec![20, 11, 10, 9],
             platform_distance_bounds: (500, 750),
+            momentum_prob: 0.01,
         }
     }
 }
diff --git a/src/editor.rs b/src/editor.rs
index c6498d1..9c4ac98 100644
--- a/src/editor.rs
+++ b/src/editor.rs
@@ -374,6 +374,14 @@ impl Editor {
                         true,
                     );
 
+                    field_edit_widget(
+                        ui,
+                        &mut self.config.momentum_prob,
+                        edit_f32,
+                        "momentum prob",
+                        true,
+                    );
+
                     // only show these in setup mode
                     ui.add_visible_ui(self.is_setup(), |ui| {
                         vec_edit_widget(
diff --git a/src/generator.rs b/src/generator.rs
index c8f3666..fea83a2 100644
--- a/src/generator.rs
+++ b/src/generator.rs
@@ -37,18 +37,18 @@ impl Generator {
 
         if !self.walker.finished {
             // randomly mutate kernel
-            self.walker.mutate_kernel(config, &mut self.rnd);
+            self.walker.mutate_kernel(&config, &mut self.rnd);
 
             // perform one step
             self.walker
-                .probabilistic_step(&mut self.map, &mut self.rnd)?;
+                .probabilistic_step(&mut self.map, config, &mut self.rnd)?;
 
             // handle platforms
             self.walker.check_platform(
                 &mut self.map,
                 config.platform_distance_bounds.0,
                 config.platform_distance_bounds.1,
-            );
+            )?;
         }
 
         Ok(())
@@ -56,7 +56,7 @@ impl Generator {
 
     /// Post processing step to fix all existing edge-bugs, as certain inner/outer kernel
     /// configurations do not ensure a min. 1-block freeze padding consistently.
-    fn fix_edge_bugs(&mut self) -> Array2<bool> {
+    fn fix_edge_bugs(&mut self) -> Result<Array2<bool>, &'static str> {
         let mut edge_bug = Array2::from_elem((self.map.width, self.map.height), false);
         let width = self.map.width;
         let height = self.map.height;
@@ -71,8 +71,12 @@ impl Generator {
                                 continue;
                             }
 
-                            let neighbor_x = x + dx - 1; // TODO: deal with overflow?
-                            let neighbor_y = y + dy - 1;
+                            let neighbor_x = (x + dx)
+                                .checked_sub(1)
+                                .ok_or("fix edge bug out of bounds")?;
+                            let neighbor_y = (y + dy)
+                                .checked_sub(1)
+                                .ok_or("fix edge bug out of bounds")?;
                             if neighbor_x < width && neighbor_y < height {
                                 let neighbor_value = &self.map.grid[[neighbor_x, neighbor_y]];
                                 if *neighbor_value == BlockType::Hookable {
@@ -90,15 +94,17 @@ impl Generator {
             }
         }
 
-        edge_bug
+        Ok(edge_bug)
     }
 
     pub fn post_processing(&mut self) {
-        self.fix_edge_bugs();
+        self.fix_edge_bugs().expect("fix edge bugs failed");
         self.map
-            .generate_room(&self.map.spawn.clone(), 4, Some(&BlockType::Start));
+            .generate_room(&self.map.spawn.clone(), 2, Some(&BlockType::Start))
+            .expect("start room generation failed");
         self.map
-            .generate_room(&self.walker.pos.clone(), 4, Some(&BlockType::Finish));
+            .generate_room(&self.walker.pos.clone(), 2, Some(&BlockType::Finish))
+            .expect("start finish room generation");
     }
 
     /// Generates an entire map with a single function call. This function is used by the CLI.
diff --git a/src/map.rs b/src/map.rs
index 600c99f..069b7b2 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -130,23 +130,35 @@ impl Map {
         Ok(())
     }
 
-    pub fn generate_room(&mut self, pos: &Position, margin: usize, zone_type: Option<&BlockType>) {
-        // TODO: ensure valid position?
+    pub fn generate_room(
+        &mut self,
+        pos: &Position,
+        margin: usize,
+        zone_type: Option<&BlockType>,
+    ) -> Result<(), &'static str> {
+        // TODO: return an error?
+        if pos.x < (margin + 1)
+            || pos.y < (margin + 1)
+            || pos.x > self.width - (margin + 1)
+            || pos.y > self.height - (margin + 1)
+        {
+            return Err("generate room out of bounds");
+        }
 
         let margin: i32 = margin.to_i32().unwrap();
 
         // carve room
         self.set_area(
-            &pos.shifted_by(-margin, -margin),
-            &pos.shifted_by(margin, margin),
+            &pos.shifted_by(-margin, -margin)?,
+            &pos.shifted_by(margin, margin)?,
             &BlockType::Empty,
             true,
         );
 
         // set platform
         self.set_area(
-            &pos.shifted_by(-(margin - 2), 1),
-            &pos.shifted_by(margin - 2, 1),
+            &pos.shifted_by(-(margin - 2), 1)?,
+            &pos.shifted_by(margin - 2, 1)?,
             &BlockType::Platform,
             true,
         );
@@ -154,8 +166,8 @@ impl Map {
         // set spawns
         if zone_type == Some(&BlockType::Start) {
             self.set_area(
-                &pos.shifted_by(-(margin - 2), 0),
-                &pos.shifted_by(margin - 2, 0),
+                &pos.shifted_by(-(margin - 2), 0)?,
+                &pos.shifted_by(margin - 2, 0)?,
                 &BlockType::Spawn,
                 true,
             );
@@ -163,12 +175,14 @@ impl Map {
         // set start/finish line
         if let Some(zone_type) = zone_type {
             self.set_area_border(
-                &pos.shifted_by(-margin - 1, -margin - 1),
-                &pos.shifted_by(margin + 1, margin + 1),
+                &pos.shifted_by(-margin - 1, -margin - 1)?,
+                &pos.shifted_by(margin + 1, margin + 1)?,
                 zone_type,
                 false,
             );
         }
+
+        Ok(())
     }
 
     fn pos_to_chunk_pos(&self, pos: Position) -> Position {
@@ -211,13 +225,16 @@ impl Map {
         top_left: &Position,
         bot_right: &Position,
         value: &BlockType,
-    ) -> bool {
-        let area = self.grid.slice(s![
-            top_left.x..=bot_right.x + 1,
-            top_left.y..=bot_right.y + 1
-        ]);
+    ) -> Result<bool, &'static str> {
+        if !self.pos_in_bounds(&top_left) || !self.pos_in_bounds(&bot_right) {
+            return Err("checking area out of bounds");
+        }
+
+        let area = self
+            .grid
+            .slice(s![top_left.x..=bot_right.x, top_left.y..=bot_right.y]);
 
-        area.iter().any(|block| block == value)
+        Ok(area.iter().any(|block| block == value))
     }
 
     pub fn check_area_all(
@@ -225,13 +242,15 @@ impl Map {
         top_left: &Position,
         bot_right: &Position,
         value: &BlockType,
-    ) -> bool {
-        let area = self.grid.slice(s![
-            top_left.x..=bot_right.x + 1,
-            top_left.y..=bot_right.y + 1
-        ]);
+    ) -> Result<bool, &'static str> {
+        if !self.pos_in_bounds(&top_left) || !self.pos_in_bounds(&bot_right) {
+            return Err("checking area out of bounds");
+        }
+        let area = self
+            .grid
+            .slice(s![top_left.x..=bot_right.x, top_left.y..=bot_right.y]);
 
-        area.iter().all(|block| block == value)
+        Ok(area.iter().all(|block| block == value))
     }
 
     // TODO: right now override is hardcoded to overide empty AND freeze. i might need some
diff --git a/src/position.rs b/src/position.rs
index ece825a..f28b3b2 100644
--- a/src/position.rs
+++ b/src/position.rs
@@ -32,13 +32,13 @@ impl Position {
     }
 
     /// returns a new position shifted by some x and y value
-    pub fn shifted_by(&self, x_shift: i32, y_shift: i32) -> Position {
+    pub fn shifted_by(&self, x_shift: i32, y_shift: i32) -> Result<Position, &'static str> {
         let new_x = match x_shift >= 0 {
             true => self.x + (x_shift as usize),
             false => self
                 .x
                 .checked_sub((-x_shift) as usize)
-                .expect("shift is out of bounds"),
+                .ok_or("invalid shift")?,
         };
 
         let new_y = match y_shift >= 0 {
@@ -46,10 +46,10 @@ impl Position {
             false => self
                 .y
                 .checked_sub((-y_shift) as usize)
-                .expect("shift is out of bounds"),
+                .ok_or("invalid shift")?,
         };
 
-        Position::new(new_x, new_y)
+        Ok(Position::new(new_x, new_y))
     }
 
     pub fn shift_in_direction(
diff --git a/src/walker.rs b/src/walker.rs
index 41c3ffb..3a90c30 100644
--- a/src/walker.rs
+++ b/src/walker.rs
@@ -2,7 +2,7 @@ use crate::{
     config::GenerationConfig,
     kernel::Kernel,
     map::{BlockType, KernelType, Map},
-    position::Position,
+    position::{Position, ShiftDirection},
     random::Random,
 };
 
@@ -21,6 +21,8 @@ pub struct CuteWalker {
     pub finished: bool,
 
     pub steps_since_platform: usize,
+
+    pub last_direction: Option<ShiftDirection>,
 }
 
 impl CuteWalker {
@@ -40,6 +42,7 @@ impl CuteWalker {
             waypoints: config.waypoints.clone(),
             finished: false,
             steps_since_platform: 0,
+            last_direction: None,
         }
     }
 
@@ -59,12 +62,17 @@ impl CuteWalker {
 
     /// will try to place a platform at the walkers position.
     /// If force is true it will enforce a platform.
-    pub fn check_platform(&mut self, map: &mut Map, min_distance: usize, max_distance: usize) {
+    pub fn check_platform(
+        &mut self,
+        map: &mut Map,
+        min_distance: usize,
+        max_distance: usize,
+    ) -> Result<(), &'static str> {
         self.steps_since_platform += 1;
 
         // Case 1: min distance is not reached -> skip
         if self.steps_since_platform < min_distance {
-            return;
+            return Ok(());
         }
 
         let walker_pos = self.pos.clone();
@@ -72,31 +80,34 @@ impl CuteWalker {
         // Case 2: max distance has been exceeded -> force platform using a room
         if self.steps_since_platform > max_distance {
             // TODO: for now this is hardcoded so that platform is shifted down by 7 blocks.
-            map.generate_room(&walker_pos.shifted_by(0, 7), 4, None);
+            // map.generate_room(&walker_pos.shifted_by(0, 7)?, 4, None)?;
             self.steps_since_platform = 0;
-            return;
+            return Ok(());
         }
 
         // Case 3: min distance has been exceeded -> Try to place platform, but only if possible
         let area_empty = map.check_area_all(
-            &walker_pos.shifted_by(-2, -3),
-            &walker_pos.shifted_by(2, 1),
+            &walker_pos.shifted_by(-2, -3)?,
+            &walker_pos.shifted_by(2, 1)?,
             &BlockType::Empty,
-        );
+        )?;
         if area_empty {
             map.set_area(
-                &walker_pos.shifted_by(-1, 0),
-                &walker_pos.shifted_by(1, 0),
+                &walker_pos.shifted_by(-1, 0)?,
+                &walker_pos.shifted_by(1, 0)?,
                 &BlockType::Platform,
                 true,
             );
             self.steps_since_platform = 0;
         }
+
+        Ok(())
     }
 
     pub fn probabilistic_step(
         &mut self,
         map: &mut Map,
+        config: &GenerationConfig,
         rnd: &mut Random,
     ) -> Result<(), &'static str> {
         if self.finished {
@@ -105,11 +116,17 @@ impl CuteWalker {
 
         let goal = self.goal.as_ref().ok_or("Error: Goal is None")?;
         let shifts = self.pos.get_rated_shifts(goal, map);
-        let sampled_shift = rnd.sample_move(&shifts);
+        let mut sampled_shift = &rnd.sample_move(&shifts);
+
+        // with a certain probabiliy re-use last direction instead
+        if rnd.with_probability(config.momentum_prob) && !self.last_direction.is_none() {
+            sampled_shift = self.last_direction.as_ref().unwrap();
+        }
 
         // apply that shift
-        self.pos.shift_in_direction(&sampled_shift, map)?;
+        self.pos.shift_in_direction(sampled_shift, map)?;
         self.steps += 1;
+        self.last_direction = Some(sampled_shift.clone());
 
         // remove blocks using a kernel at current position
         map.update(self, KernelType::Outer)?;