diff --git a/demo/include/grid.hpp b/demo/include/grid.hpp
index 158c56d85f6c97ae4cedbf34863a06bf2d48f1a9..62ecb1de1bbe0bd3efeee24597166b4978c97907 100644
--- a/demo/include/grid.hpp
+++ b/demo/include/grid.hpp
@@ -91,7 +91,11 @@ namespace demo {
 				} else if (cell.direction == 3) {
 					moveDir.x = -1;
 				}
-				cell.pos += moveDir;
+
+				if ( m_grid->canMove(cell.pos, moveDir) ) {
+					cell.pos += moveDir;
+				}
+
 			}
 
 			inline void rotate(bool clockwise) {
diff --git a/include/fggl/entity/gridworld/zone.hpp b/include/fggl/entity/gridworld/zone.hpp
index 376c7db11640dde4a1f638b936b71184cd4b3ed7..38a14decba8be1a59bd8091ea17e89f02cb8c746 100644
--- a/include/fggl/entity/gridworld/zone.hpp
+++ b/include/fggl/entity/gridworld/zone.hpp
@@ -98,6 +98,11 @@ namespace fggl::entity::grid {
 				clear();
 			}
 
+			inline bool inBounds(GridPos pos) const {
+				return 0 <= pos.x && pos.x <= width
+				    && 0 <= pos.y && pos.y <= height;
+			}
+
 			void clear() {
 				WallState noWall;
 
@@ -135,7 +140,10 @@ namespace fggl::entity::grid {
 			}
 
 			inline bool canMove(GridPos pos) const {
-				return m_tiles.m_floors[m_floors.getCell(pos)] != 0;
+				if ( !inBounds(pos) ) {
+					return false;
+				}
+				return m_tiles.m_floors[m_floors.get(pos)].moveCost != FloorTile::IMPOSSIBLE;
 			}
 
 			inline bool canMove(GridPos pos, math::vec2i dir) const {
@@ -143,11 +151,25 @@ namespace fggl::entity::grid {
 			}
 
 			inline bool blocked(GridPos pos, math::vec2i dir) const {
-				if ( dir.x == -1 || dir.y == -1 ) {
-					return m_walls.getCell(pos) != 0;
-				} else {
-					m_walls.getCell(pos + dir) != 0;
+				auto targetPos = pos;
+				if ( dir.x == 1 || dir.y == 1 ) {
+					targetPos = pos + dir;
+				}
+
+				if ( !inBounds(targetPos) ) {
+					return true;
+				}
+
+				auto& wallObj = m_walls.get(targetPos);
+				if ( dir.y != 0 ) {
+					return wallObj.north != 0;
 				}
+
+				if (dir.x != 0) {
+					return wallObj.west != 0;
+				}
+
+				return true;
 			}
 
 			EntityManager& entities() {