-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGameTree.c
177 lines (161 loc) · 5.05 KB
/
GameTree.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Player.h"
#include "Game.h"
#include "GameTree.h"
// I won't perform non-critical tests here because they will use precious time
Node* new_node(Node* parent, Player* player, int** grid, int gridx, int gridy,
int** pos, int last1, int last2) {
Node* node = malloc(sizeof(Node));
if(!node) {
printf("Out of memory or something like that.\n");
return NULL;
}
node->parent = parent;
node->player = player;
node->grid = grid;
node->pos = pos;
node->gridx = gridx;
node->gridy = gridy;
node->terminal = game_over(grid, gridx, gridy, pos);
node->n_child = 0;
node->pointer = NULL;
node->children = NULL;
node->last1 = last1;
node->last2 = last2;
if (parent) node->depth = parent->depth+1;
else node->depth = 1;
node->value = -INFINITY;
return node;
}
// Copy a pointer of pointer of int
int** copy_grid(int** grid, int gridx, int gridy) {
int** copy = malloc(gridx*sizeof(int*));
if(!copy) {
printf("Out of memory or something like that.\n");
return NULL;
}
for (int i = 0; i<gridx; i++) {
copy[i] = malloc(gridy*sizeof(int));
if(!copy[i]) {
for (int j = 0; j<i; j++) {
free(copy[j]);
}
free(copy);
printf("Out of memory.\n");
return NULL;
}
for (int j = 0; j<gridy; j++) {
copy[i][j] = grid[i][j];
}
}
return copy;
}
// This assumes nodes have been evaluated
// Right now, those just return min and max value, but i might need to add some
// stuff to allow me to find the next node without having to look for it
double min(Node** nodes, int n_nodes) {
double min = INFINITY;
for (int i = 0; i<n_nodes; i++) {
if (!nodes[i]) continue;
if (nodes[i]->value < min) min = nodes[i]->value;
}
return min;
}
// This assumes nodes have been evaluated
double max(Node** nodes, int n_nodes) {
double max = -INFINITY;
for (int i = 0; i<n_nodes; i++) {
if (!nodes[i]) continue;
if (nodes[i]->value > max) max = nodes[i]->value;
}
return max;
}
// This creates all the subsequent game positions for moves made by player id
// Note that this does generate impossible positions
int spawn_children(Node* parent, int id) {
if (!parent) return 0;
// we won't spawn children of a game that is over
if (parent->terminal) return 0;
if (parent->n_child) return -2;
parent->n_child = 3;
int** new_grid;
int** new_pos;
parent->children = malloc(3 * sizeof(Node*));
if(!parent->children) {
printf("Out of memory!\n");
return -1;
}
int count = 0;
if(id) {
for (int i = 0; i<4; i++) {
//This is to avoid generating a backwards move. This is especialy usefull
//to avoid making an illegal first move.
if ((parent->last2+2)%4 == i) continue;
new_grid = copy_grid(parent->grid, parent->gridx, parent->gridy);
new_pos = copy_grid(parent->pos, 2, 2);
make_move(new_grid, parent->gridx, parent->gridy, new_pos, id, i);
parent->children[count] = new_node(parent, parent->player, new_grid,
parent->gridx, parent->gridy, new_pos, parent->last1, i);
count++;
}
} else {
for (int i = 0; i<4; i++) {
if ((parent->last1+2)%4 == i) continue;
new_grid = copy_grid(parent->grid, parent->gridx, parent->gridy);
new_pos = copy_grid(parent->pos, 2, 2);
make_move(new_grid, parent->gridx, parent->gridy, new_pos, id, i);
parent->children[count] = new_node(parent, parent->player, new_grid,
parent->gridx, parent->gridy, new_pos, i, parent->last2);
count++;
}
}
return 3;
}
//Frees memory allocated to a node. Will recursively free memory allocated to
// childs too, beware.
// This function returns null because we will somethimes need to set a pointer
// to NULL after freeing it.
void free_node(Node* node) {
if (!node) return;
if (node->n_child) {
for (int i = 0; i<node->n_child; i++) {
free_node(node->children[i]);
}
free(node->children);
}
if (node->grid) {
for (int i = 0; i<node->gridx; i++) {
free(node->grid[i]);
}
free(node->grid);
}
if (node->pos) {
for (int i = 0; i<2; i++) {
free(node->pos[i]);
}
free(node->pos);
}
if (node->pointer) *node->pointer = NULL;
free(node);
}
Tree* new_tree(Node* root) {
Tree* tree = malloc(sizeof(Tree));
if(!tree) {
printf("Out of memory or something like that.\n");
return NULL;
}
tree->depth = 1;
tree->root = root;
tree->last_level = malloc(sizeof(Node*));
tree->last_level[0] = root;
tree->num_nodes = 1;
return tree;
}
void free_tree(Tree* tree) {
if (!tree) return;
free_node(tree->root);
free(tree->last_level);
free(tree);
}