Hi,
Here is one algorithm I think might do what you are looking for, though there are a lot of ways to define direction and rules. In my case, there is a grid and you can go up, down, left, and right, but cannot go outside the grid or return from the same position you just came from.
The example below shows the final grid with how often each position was visited, and a dataframe that shows the trace of the path. Note that it's easy to start going in circles as revisiting the previous path is reinforced as you were asking.
library(dplyr)
set.seed(2) #Only needed for reproducibility
#Create the grid
nRow = 10
nCol = 10
myGrid = matrix(1, nrow = nRow, ncol = nCol)
#Starting position
x = 1 # x-axis is horizontal (row), with 0 at top
y = 1 # y-axis is vertical (column), with 0 at top
nSteps = 25
#Keep track of previous direction and path
prevDir = NULL
path = data.frame()
#Run algorithm for n steps
for(i in 1:nSteps){
#Add 1 to current position
myGrid[y,x] = myGrid[y,x] + 1
#Get the values up, down, left and right (0 if outside the grid)
prob = c(max(0,myGrid[y-1,x]), max(0,myGrid[y,(x+1) %% (nCol+1)]),
max(0,myGrid[(y+1) %% (nRow+1),x]), max(0,myGrid[y,x-1]))
#Prevent going back from where we came before (comment out if allowed)
prob[prevDir] = 0
#Calculate the probability of moving to any of the directions
# based on the times it has been visited before
prob = prob / sum(prob)
#Pick a direction (and save the previous one)
nextDir = sample(1:4, 1, prob = prob)
prevDir = (nextDir+1) %% 4 + 1 #e.g. When we go up (1), do not go down (3) next step
#Keep track of the path (comment out if not needed)
path = bind_rows(path, list(x = x, y = y,
dir = c("up", "right", "down", "left")[nextDir]))
#Get the next x-coordinate
x = case_when(
nextDir == 2 ~ x + 1,
nextDir == 4 ~ x - 1,
TRUE ~ x
)
#Get the next y-coordinate
y = case_when(
nextDir == 1 ~ y - 1,
nextDir == 3 ~ y + 1,
TRUE ~ y
)
}
myGrid - 1 #Remove the default 1 to see how often a cell was visited
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 2 1 0 0 0 0 0 0 0 0
#> [2,] 1 2 0 1 1 0 0 0 0 0
#> [3,] 0 2 3 2 1 0 0 0 0 0
#> [4,] 0 0 2 1 0 0 0 0 0 0
#> [5,] 0 0 1 1 1 0 0 0 0 0
#> [6,] 0 0 1 1 1 0 0 0 0 0
#> [7,] 0 0 0 0 0 0 0 0 0 0
#> [8,] 0 0 0 0 0 0 0 0 0 0
#> [9,] 0 0 0 0 0 0 0 0 0 0
#> [10,] 0 0 0 0 0 0 0 0 0 0
paste(path$dir, collapse = " - ") #The full path (starting at 1,1 (top left))
#> [1] "right - down - down - right - right - right - up - left -
# down - left - down - right - down - right - down - left - left -
# up - up - up - left - up - left - up - right"
Created on 2022-04-02 by the reprex package (v2.0.1)
Hope this helps,
PJ