2025-06-14 23:26:42 +02:00

149 lines
4.2 KiB
C

#include <stdio.h>
#include <string.h>
#include "lee-algorithm.h"
#include "../stack/stack.h"
#include "../cell/cell.h"
#include "../communication/utils.h"
#include "../robot/robot.h"
// Maze en standaard Lee-functies
int unexpanded_matrix[MAZE_SIZE][MAZE_SIZE] = {
{ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1},
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1},
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1},
{ -1, -1, -1, 0, -1, 0, -1, 0, -1, -1, -1,}
};
const cell neighbours[4] = {{-1, 0}, {0, 1}, {1,}, {0, -1}}; // NORTH EAST SOUTH WEST
const cell crossing_neighbours[4] = {{-2, 0}, {0, 2}, {2,0}, {0, -2}};
void lee_run(robot r, cell targetCell, stack *moves) {
int assignmentMatrix[MAZE_SIZE][MAZE_SIZE];
memcpy(assignmentMatrix, unexpanded_matrix, sizeof(assignmentMatrix));
lee_expand(assignmentMatrix, r.pos, targetCell);
lee_trace(assignmentMatrix, r, targetCell, moves);
stack_invert(moves);
}
void lee_expand(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], cell startCell, cell targetCell) {
int v = 1;
assignmentMatrix[targetCell.x][targetCell.y] = v;
while (assignmentMatrix[startCell.x][startCell.y] == 0) {
for (int i = 0; i < MAZE_SIZE; i++) {
for (int j = 0; j < MAZE_SIZE; j++) {
if (assignmentMatrix[i][j] == v) {
for (int k = 0; k < 4; k++) {
cell neighbour;
cell_add(&neighbour, (cell){i, j}, neighbours[k]);
if (isInBound(neighbour) && assignmentMatrix[neighbour.x][neighbour.y] == 0) {
assignmentMatrix[neighbour.x][neighbour.y] = v + 1;
}
}
}
}
}
v += 1;
}
}
void lee_trace(int assignmentMatrix[MAZE_SIZE][MAZE_SIZE], robot r, cell targetCell, stack *stack) {
robot tempBot = r;
printf("\n");
while (!cell_equals(tempBot.pos, targetCell)) {
// check forward first,as its most efficient move
cell neighbourCell;
cell_add(&neighbourCell, tempBot.pos, neighbours[tempBot.dir]);
if (isInBound(neighbourCell) &&
assignmentMatrix[neighbourCell.x][neighbourCell.y] > 0 &&
assignmentMatrix[neighbourCell.x][neighbourCell.y] < assignmentMatrix[tempBot.pos.x][tempBot.pos.y]) {
tempBot.pos = neighbourCell;
//if (isValidCrossing(tempBot.pos) ) {
stack_push(stack, neighbours[tempBot.dir]);
//}
continue;
}
// check rest of directions
for (int i = 0; i < 4; i++) {
cell_add(&neighbourCell, tempBot.pos, neighbours[(tempBot.dir + i) % 4]);
//ugly calculation as to check all 3 other directions other than the main one
if (isInBound(neighbourCell) &&
assignmentMatrix[neighbourCell.x][neighbourCell.y] > 0 &&
assignmentMatrix[neighbourCell.x][neighbourCell.y] < assignmentMatrix[tempBot.pos.x][tempBot.pos.y]) {
tempBot.pos = neighbourCell;
spin(&r, tempBot.dir);
//if (isValidCrossing(tempBot.pos)) {
stack_push(stack, neighbours[(tempBot.dir + i) % 4]);
//}
break;
}
}
}
}
int validatePath(robot r, stack s) {
robot temp = r;
for (int i = 0; i < s.length; i++) {
cell_add(&temp.pos, temp.pos,s.data[i]);
if (unexpanded_matrix[temp.pos.x][temp.pos.y] < 0) {
return 0;
}
}
return 1;
}
extern int firstMove;
void followPath(robot *r, stack *path,int visited[MAZE_SIZE][MAZE_SIZE]) {
while (path->length > 0) {
cell currentCell = stack_pop(path);
int result = move(r,currentCell);
comm_await_crossing(2000);
comm_discard_sensor_data(1000);
visited[r->pos.x][r->pos.y] = 5;
if (result == 0) {
move(r,currentCell);
comm_await_crossing(2000);
comm_discard_sensor_data(1000);
visited[r->pos.x][r->pos.y] = 5;
}
printMatrix_with_current_pos(visited,*r);
}
}
int isInBound(const cell c) {
if (c.x >= 0 && c.x < MAZE_SIZE &&
c.y >= 0 && c.y < MAZE_SIZE) {
return 1;
}
return 0;
}
int isStation(const cell c) {
if (c.x == 0 || c.x == MAZE_SIZE - 1 ||
c.y == 0 || c.y == MAZE_SIZE - 1){
return 1;
}
return 0;
}
int isValidCrossing(const cell c) {
if (c.x > 0 && c.x < MAZE_SIZE - 1 &&
c.y > 0 && c.y < MAZE_SIZE - 1 &&
c.x % 2 == 1 && c.y % 2 == 1 &&
unexpanded_matrix[c.x][c.y]==0) {
return 1;
}
return 0;
}