Skip to content

Commit a200937

Browse files
authored
Add files via upload
1 parent 743e358 commit a200937

33 files changed

Lines changed: 1422 additions & 0 deletions
828 KB
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
project(rev6 C)
3+
4+
set(CMAKE_C_STANDARD 99)
5+
6+
add_executable(rev6 test.c api.c)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include "ai.h"
2+
3+
int *find_target(GameBoard *gb) {
4+
for (int i = 0; i < BOARD_SIZE; i++) {
5+
for (int j = 0; j < BOARD_SIZE; j++) {
6+
if (gb->cell_value[i][j] != 0) {
7+
int *target = calloc(2, sizeof(int));
8+
target[0] = j;
9+
target[1] = i;
10+
return target;
11+
}
12+
}
13+
}
14+
return NULL;
15+
}
16+
17+
int coord_equal(int *c1, int *c2) {
18+
if (c1[0] == c2[0] && c1[1] == c2[1]) return 1;
19+
return 0;
20+
}
21+
22+
int move_available(GameBoard *gb, int *move) {
23+
int *next_square = next_position(gb->snek->head->coord, move);
24+
if (next_square[0] > BOARD_SIZE - 1 || next_square[0] < 0 || next_square[1] > BOARD_SIZE - 1 ||
25+
next_square[1] < 0) { // out of range
26+
free(next_square);
27+
return 0;
28+
}
29+
if (gb->occupancy[next_square[1]][next_square[0]] &&
30+
!coord_equal(next_square, gb->snek->tail->coord)) { // hitting itself
31+
free(next_square);
32+
return 0;
33+
}
34+
free(next_square);
35+
return 1;
36+
}
37+
38+
int *next_position(int *coord, int *move) {
39+
int *next = calloc(2, sizeof(int));
40+
next[0] = coord[0];
41+
next[1] = coord[1];
42+
next[move[0]] += move[1];
43+
return next;
44+
}
45+
46+
int target_next(int *head, int *target) {
47+
if (target == NULL) return 0;
48+
if (head[0] == target[0] && abs(head[1] - target[1]) == 1) return 1;
49+
if (head[1] == target[1] && abs(head[0] - target[0]) == 1) return 1;
50+
return 0;
51+
}
52+
53+
GameBoard *update_gameboard(GameBoard *gb, int *move, int *target) {
54+
GameBoard *new_gb = malloc(sizeof(GameBoard));
55+
new_gb->snek = malloc(sizeof(Snek));
56+
new_gb->snek->head = malloc(sizeof(SnekBlock));
57+
new_gb->snek->length = gb->snek->length;
58+
// cell value is not needed since the target has been located already
59+
int *new_head = next_position(gb->snek->head->coord, move);
60+
new_gb->snek->head->coord[0] = new_head[0];
61+
new_gb->snek->head->coord[1] = new_head[1];
62+
new_gb->snek->head->next = gb->snek->head;
63+
64+
// now update occupancy and also update snake tail OR length if needed
65+
SnekBlock *curr = new_gb->snek->head;
66+
int tail_next = 0;
67+
68+
while (curr->next && !tail_next) { // change
69+
new_gb->occupancy[curr->coord[1]][curr->coord[0]] = 1;
70+
if (coord_equal(curr->next->coord, gb->snek->tail->coord)) tail_next = 1;
71+
else curr = curr->next;
72+
}
73+
if (target_next(gb->snek->head->coord, target)) {
74+
new_gb->occupancy[curr->next->coord[1]][curr->next->coord[0]] = 1; // adding in previous tail
75+
new_gb->snek->length++;
76+
new_gb->snek->tail = curr->next;
77+
} else {
78+
new_gb->snek->tail = curr; // making new tail
79+
}
80+
81+
return new_gb;
82+
}
83+
84+
int n_predictor(int n, GameBoard *gb, int *move, int *target) {
85+
// The brain of the AI: checks if after n moves the Snake will be trapped
86+
87+
if (!move_available(gb, move)) return 0; // base case 1
88+
89+
if (n == 0) { // base case 2
90+
int sum = 0;
91+
int *new_move = calloc(2, sizeof(int));
92+
for (int ax = 0; ax < 2; ax++) {
93+
for (int dir = -1; dir < 2; dir += 2) {
94+
new_move[0] = ax;
95+
new_move[1] = dir;
96+
if (move_available(gb, new_move)) sum += 1;
97+
}
98+
}
99+
return sum;
100+
}
101+
102+
// move is available, so check all possible paths after said move
103+
GameBoard *new_gb = update_gameboard(gb, move, target);
104+
int non_traps = 0;
105+
int *new_move = calloc(2, sizeof(int));
106+
for (int ax = 0; ax < 2; ax++) {
107+
for (int dir = -1; dir < 2; dir += 2) {
108+
new_move[0] = ax;
109+
new_move[1] = dir;
110+
non_traps += n_predictor(n - 1, new_gb, new_move, target); // recursive step: worst case O(4^n)
111+
}
112+
}
113+
return non_traps;
114+
}
115+
116+
117+
int *survival(GameBoard *gb, int n) {
118+
// 1. Check to see if a move towards the target that ensures n moves is possible
119+
int *target = find_target(gb);
120+
int *head = gb->snek->head->coord;
121+
int target_xdir = 0;
122+
int target_ydir = 0;
123+
int *move = calloc(2, sizeof(int));
124+
125+
if (target) {
126+
if (head[0] < target[0]) target_xdir = 1;
127+
else if (head[0] > target[0]) target_xdir = -1;
128+
if (head[1] < target[1]) target_ydir = 1;
129+
else if (head[1] > target[1]) target_ydir = -1;
130+
}
131+
132+
if (target_xdir != 0) {
133+
move[0] = x;
134+
move[1] = target_xdir;
135+
if (n_predictor(n, gb, move, target) > 0) return move;
136+
}
137+
if (target_ydir != 0) {
138+
move[0] = y;
139+
move[1] = target_ydir;
140+
if (n_predictor(n, gb, move, target) > 0) return move;
141+
}
142+
143+
// 2. Check to see if any other moves are available that ensure at least n further moves
144+
for (int ax = 0; ax < 2; ax++) {
145+
for (int dir = -1; dir < 2; dir += 2) {
146+
move[0] = ax;
147+
move[1] = dir;
148+
if (n_predictor(n, gb, move, target) > 0) return move;
149+
}
150+
}
151+
152+
// 3. If no moves ensure at least n further moves, then choose an available move. If no moves available, go up to die.
153+
for (int ax = 0; ax < 2; ax++) {
154+
for (int dir = -1; dir < 2; dir += 2) {
155+
move[0] = ax;
156+
move[1] = dir;
157+
if (move_available(gb, move)) return move;
158+
}
159+
}
160+
return move;
161+
}
162+
163+
164+
165+
166+
167+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "api.h"
2+
3+
int *find_target(GameBoard *gb);
4+
5+
int coord_equal(int *c1, int *c2);
6+
7+
int move_available(GameBoard *gb, int *next_square);
8+
9+
int *next_position(int *coord, int *move);
10+
11+
int target_next(int *head, int *target);
12+
13+
GameBoard *update_gameboard(GameBoard *gb, int *move, int *target);
14+
15+
int n_predictor(int n, GameBoard *gb, int *move, int *target);
16+
17+
int *survival(GameBoard *gb, int n);
18+

0 commit comments

Comments
 (0)