My enemy randomly paths away from player in maze-solving game

35 views (last 30 days)
I have a maze generator that the player attempts to solve, and an enemy randomly spawns in the maze. It attempts to path towards the player and match their location index (in theory). In practice, however, it will move away from the player for extended periods before pathing back.
The code in question is the "if pR > enemyR; enemyR = enemyR + randi([0,2]);
In theory, this should move the enemy position down if the player is below and up if the player is above, same for left and right. Any ideas as to why it tends to wander off?
function drawMaze(maze, playerRow, playerCol, goalPos, enemyPos)
% Draw maze
imagesc(maze);
colormap("sky"); % Define colors
axis equal tight off;
% Draw player sprite
hold on;
plot(playerCol, playerRow, 'ko', 'MarkerSize', 9, 'MarkerFaceColor', 'k');
%draw goal position
plot(goalPos(1),goalPos(2),'bo', 'MarkerSize', 9);
%draw enemy position
plot(enemyPos(1),enemyPos(2),'ro','MarkerSize', 9, 'MarkerFaceColor', 'r');
hold off;
drawnow;
end
% Welcome Message
welcomeMsg = 'Welcome to our game! Press OK to start. Use the arrow keys to move. Try to get to the bottom right!';
gameStart = questdlg(welcomeMsg,'Start Game', 'OK','Cancel','Ok');
% Start game
if strcmp(gameStart,'OK')
%Prompt player to select difficulty (map size)
diffSelect = questdlg('Select a difficulty','Welcome','Easy','Medium','Hard','Medium');
diff = 0; %initialize difficulty selection
DC = 0; %initialie DC
switch diffSelect
case 'Easy'
diff = 4;
case 'Medium'
diff = 5;
case 'Hard'
diff = 9;
end
map = mapMaze(2,1,'MapSize',[diff,diff],'MapResolution',diff); % create map
mapMatrix = getOccupancy(map); % create an array from generated map
startR = 0; % initialize starting index
startC = 0;
for c = size(mapMatrix,2):-1:1
for r = 1:1:size(mapMatrix,1)
if mapMatrix(r,c) == 0 % find first zero in top left
startR = r; % save as starting index
startC = c;
break
end
end
end
goal = [0,0]; %initialize goal
for c = 1:1:size(mapMatrix,2) %find last zero in bottom right
for r = 1:1:size(mapMatrix,1)
if mapMatrix(r,c) == 0
goal(1) = r;
goal(2) = c; % save as goal index
end
end
end
enemy = [0,0];
enemy(1) = randi([1,size(mapMatrix,1)]); % randomly place enemy on map
enemy(2) = randi([1,size(mapMatrix,2)]);
while mapMatrix(enemy(1),enemy(2)) ~= 0 % if enemy is placed in wall
enemy(1) = randi([1,size(mapMatrix,1)]);
enemy(2) = randi([1,size(mapMatrix,2)]); % re-do until placed in maze
end
pR = startR; % Player starting location
pC = startC;
fig = figure;
drawMaze(mapMatrix, pR, pC, goal, enemy) % display initial map
while true % Start game loop
% Wait for user input
keyPress = waitforbuttonpress;
if keyPress == 0 % a mouse click
continue;
end
newR = pR; % get current position
newC = pC;
enemyR = enemy(1);
enemyC = enemy(2);
%randomizer = [-1,0,0,1];
key = fig.CurrentCharacter;
switch key % Update player position based on input key pressed
case 30 %up
newR = pR - 1;
case 31 %down
newR = pR + 1;
case 28 %left
newC = pC - 1;
case 29 %right
newC = pC + 1;
end
%check if new position is valid
if newR >= 1 && newR <= size(mapMatrix, 1) && ...
newC >= 1 && newC <= size(mapMatrix, 2) && ...
mapMatrix(newR, newC) == 0
% if valid, update player position
pR = newR;
pC = newC;
end
if pR > enemyR % if player is below enemy, move down
enemyR = enemyR + randi([0,2]);
elseif pR < enemyR % if player is above enemy, move up
enemyR = enemyR - randi([0,2]);
end
if pC > enemyC % if player is right of enemy, move right
enemyC = enemyC + randi([0,2]);
elseif pC < enemyC % if player is left of enemy, move left
enemyC = enemyC - randi([0,2]);
end
if enemyR >= 1 && enemyR <= size(mapMatrix, 1) && ...
enemyC >= 1 && enemyC <= size(mapMatrix, 2)
enemy(1) = enemyR;
enemy(2) = enemyC;
end
% check if player has reached the goal
if pR == goal(1) && pC == goal(2)
win = questdlg('You win! Would you like to play again?','Congratulations!','Yes','No','Yes');
if strcmp(win,'Yes')
diffSelect = questdlg('Select a difficulty','Welcome','Easy','Medium','Hard','Medium');
switch diffSelect
case 'Easy'
diff = 4;
case 'Medium'
diff = 5;
case 'Hard'
diff = 9;
end
map = mapMaze(2,1,'MapSize',[diff,diff],'MapResolution',diff);
mapMatrix = getOccupancy(map);
pR = startR;
pC = startC;
for c = 1:1:size(mapMatrix,2)
for r = 1:1:size(mapMatrix,1)
if mapMatrix(r,c) == 0
goal(1) = r;
goal(2) = c; % save as goal index
end
end
end
for c = size(mapMatrix,2):-1:1
for r = 1:1:size(mapMatrix,1)
if mapMatrix(r,c) == 0 % find first zero in top left
startR = r; % save as starting index
startC = c;
break
end
end
end
else
break
end
end
drawMaze(mapMatrix,pR,pC, goal, enemy)
end
end

Answers (1)

Umeshraja
Umeshraja on 20 Nov 2024 at 6:43
Hi @John,
I assume that the enemy always take the shortest path and takes moves only one step at a time. The core issue lies in enemy movement logic and the current limitation in your code are
  • Direct Movement: The enemy moves directly towards the player without considering walls, which can lead to it getting stuck or moving away when there's no valid direct path.
  • Path Direction: The horizontal and vertical movements are handled separately, which can result in zigzag patterns or inefficient paths.
To improve this, we can implement a more efficient algorithm such as Breadth-First Search (BFS). BFS takes maze walls into account and finds valid paths around obstacles, ensuring the enemy always takes the shortest path while moving one step at a time.
In this script, the player is represented in black, the goal is blue, and the enemy is red. Please refer to the attached file for implementation details.
Hope it helps!

Products


Release

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!