diff --git a/client/HeroMovementController.cpp b/client/HeroMovementController.cpp
index 81a625d12..6b1152f60 100644
--- a/client/HeroMovementController.cpp
+++ b/client/HeroMovementController.cpp
@@ -100,7 +100,8 @@ void HeroMovementController::showTeleportDialog(const CGHeroInstance * hero, Tel
 		}
 	}
 
-	assert(0); // exit not found? How?
+	// may happen when hero has path but does not moves alongside it
+	// for example, while standing on teleporter set path that does not leads throught teleporter and press space
 	LOCPLINT->cb->selectionMade(-1, askID);
 	return;
 }
diff --git a/lib/mapObjects/CGCreature.cpp b/lib/mapObjects/CGCreature.cpp
index ca661dc8e..f76915582 100644
--- a/lib/mapObjects/CGCreature.cpp
+++ b/lib/mapObjects/CGCreature.cpp
@@ -215,12 +215,8 @@ void CGCreature::pickRandomObject(CRandomGenerator & rand)
 			subID = VLC->creh->pickRandomMonster(rand, 7);
 			break;
 	}
-
-	if (ID != MapObjectID::MONSTER)
-	{
-		ID = MapObjectID::MONSTER;
-		setType(ID, subID);
-	}
+	ID = MapObjectID::MONSTER;
+	setType(ID, subID);
 }
 
 void CGCreature::initObj(CRandomGenerator & rand)
diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp
index 92893cdbf..c825899e2 100644
--- a/lib/mapping/CMap.cpp
+++ b/lib/mapping/CMap.cpp
@@ -348,13 +348,8 @@ int3 CMap::guardingCreaturePosition (int3 pos) const
 	{
 		for (CGObjectInstance* obj : posTile.visitableObjects)
 		{
-			if(obj->isBlockedVisitable())
-			{
-				if (obj->ID == Obj::MONSTER) // Monster
-					return pos;
-				else
-					return int3(-1, -1, -1); //blockvis objects are not guarded by neighbouring creatures
-			}
+			if (obj->ID == Obj::MONSTER)
+				return pos;
 		}
 	}
 
diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp
index 61cf7aa48..a713b5bdc 100644
--- a/lib/pathfinder/CPathfinder.cpp
+++ b/lib/pathfinder/CPathfinder.cpp
@@ -24,11 +24,45 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+bool CPathfinderHelper::canMoveFromNode(const PathNodeInfo & source) const
+{
+	// we can always make the first step, even when standing on object
+	if(source.node->theNodeBefore == nullptr)
+		return true;
+
+	if (!source.nodeObject)
+		return true;
+
+	if (!source.isNodeObjectVisitable())
+		return true;
+
+	// we can always move from visitable object if hero has teleported here (e.g. went through monolith)
+	if (source.node->isTeleportAction())
+		return true;
+
+	// we can go through garrisons
+	if (source.nodeObject->ID == MapObjectID::GARRISON || source.nodeObject->ID == MapObjectID::GARRISON2)
+		return true;
+
+	// or through border gate (if we stand on it then we already have the key)
+	if (source.nodeObject->ID == MapObjectID::BORDER_GATE)
+		return true;
+
+	// or "through" boat, but only if this is embarking
+	if (source.nodeObject->ID == MapObjectID::BOAT && source.node->action == EPathNodeAction::EMBARK)
+		return true;
+
+	return false;
+}
+
 std::vector<int3> CPathfinderHelper::getNeighbourTiles(const PathNodeInfo & source) const
 {
 	std::vector<int3> neighbourTiles;
-	neighbourTiles.reserve(8);
 
+	if (!canMoveFromNode(source))
+		return neighbourTiles;
+
+	neighbourTiles.reserve(8);
 	getNeighbours(
 		*source.tile,
 		source.node->coord,
@@ -38,7 +72,7 @@ std::vector<int3> CPathfinderHelper::getNeighbourTiles(const PathNodeInfo & sour
 
 	if(source.isNodeObjectVisitable())
 	{
-		vstd::erase_if(neighbourTiles, [&](const int3 & tile) -> bool 
+		vstd::erase_if(neighbourTiles, [&](const int3 & tile) -> bool
 		{
 			return !canMoveBetween(tile, source.nodeObject->visitablePos());
 		});
@@ -136,6 +170,9 @@ void CPathfinder::calculatePaths()
 			if(neighbour->locked)
 				continue;
 
+			if (source.node->theNodeBefore && source.node->theNodeBefore->coord == neighbour->coord )
+				continue; // block U-turns
+
 			if(!hlp->isLayerAvailable(neighbour->layer))
 				continue;
 
diff --git a/lib/pathfinder/CPathfinder.h b/lib/pathfinder/CPathfinder.h
index af12ca56a..4203c8ba1 100644
--- a/lib/pathfinder/CPathfinder.h
+++ b/lib/pathfinder/CPathfinder.h
@@ -79,6 +79,7 @@ public:
 	virtual ~CPathfinderHelper();
 	void initializePatrol();
 	bool isHeroPatrolLocked() const;
+	bool canMoveFromNode(const PathNodeInfo & source) const;
 	bool isPatrolMovementAllowed(const int3 & dst) const;
 	void updateTurnInfo(const int turn = 0);
 	bool isLayerAvailable(const EPathfindingLayer & layer) const;