-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolve.c
162 lines (148 loc) · 4.53 KB
/
solve.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
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* solve.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: rgaia <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2017/11/04 02:32:20 by rgaia #+# #+# */
/* Updated: 2017/12/02 19:35:21 by rgaia ### ########.fr */
/* */
/* ************************************************************************** */
#include "fillit.h"
t_point *point_new(int row, int col)
{
t_point *new;
new = ft_memalloc(sizeof(t_point));
new->row = row;
new->col = col;
return (new);
}
/*
** Checks if a tetrimino will fit starting at a point in the map
** tmp == -1 : special case for map_size 3
** tmp > 0 : cases for map_size > 4
** tmp == 0: offset complete -> proceed as if map_size == 4
** condition needed to keep going through piece
** TODO: add case for verify_check_fit when a piece meets BOTH
** following conditions:
** 1) positive length >= 2
** 2) ft_abs(negative length) >= 2
** Currently works only if either is met, not both
** e.g.: ..##
** .##.
*/
int check_fit(t_piece *tetri, t_point *point, t_map *map)
{
int size;
static int tmp[2];
char *piece;
char **grid;
piece = tetri->piece;
size = map->size;
grid = map->grid;
if (verify_check_fit(tetri, point, size) == 0)
return (0);
while (*piece && point->row < size)
{
if (tmp[0] == 0)
{
check_reset(point, size);
if (verify_grid_set_tmp(piece, point, map, &tmp[0]) == 0)
break ;
increment_col_piece(point, &piece);
}
else if (tmp[0] == -1)
increment_piece(&piece, &tmp[0]);
else
offset_column(point, &tmp[0], size);
}
return (check_fit_return(piece, point));
}
/*
** Since place_tetrimino and remove_tetrimino are same implementation,
** with difference that the first inserts a '#' at locations, and second
** inserts a '.', we insert a dot to remove tetrimino, and insert a # to
** place tetrimino.
*/
void io_tet(char i_r, char *piece, t_point *point, t_map *map)
{
int tmp;
int i;
tmp = 0;
while (*piece)
{
if (tmp == 0)
{
check_reset(point, map->size);
if (*piece == CHR_PIECE && point->row < map->size)
{
i = (point->col == -1 ? 1 : 0);
if (*piece == CHR_PIECE && *(piece + 1) == CHR_FIELD)
tmp = (map->size) - TET_SIZE;
(i_r != CHR_FIELD ? map->grid[point->row][point->col + i] = i_r
: (map->grid[point->row][point->col + i] = CHR_FIELD));
}
increment_col_piece(point, &piece);
}
else if (tmp == -1)
increment_piece(&piece, &tmp);
else
offset_column(point, &tmp, map->size);
}
ft_memdel((void**)&point);
}
int solve_recursive(t_list *tetriminos, t_map *map)
{
t_piece *piece;
int row;
int col;
if (tetriminos->content == NULL)
return (1);
piece = (t_piece *)(tetriminos->content);
row = -1;
while ((++row <= ((map->size == 3 ? (map->size + 1) : (map->size))
- piece->height)))
{
col = -1;
while ((++col <= ((map->size == 3 ? (map->size + 1) : (map->size))
- piece->length)))
{
if (check_fit(piece, point_new(row, col), map))
{
io_tet(piece->letter, piece->piece, point_new(row, col), map);
if (solve_recursive(tetriminos->next, map))
return (1);
io_tet(CHR_FIELD, piece->piece, point_new(row, col), map);
}
}
}
return (0);
}
/*
** go through recursive backtracking call as many times as necessary until we
** find a solution. If we do not find a solution,
** try again with a map size incremented by 1.
** before calling again recursive backtracking function,
** delete previously used map, and
** create a new one of size++. Do this way for now, but later have a maximum
** size map already initiated at init_map, yet filled only up to the necessary
** amount, the rest of indexes filled with NULLs so at increment_size we
** may overwrite back to '.' with an additional index
*/
t_map *solve(t_list *tetriminos)
{
t_map *map;
int map_size;
map_size = 3;
while ((map_size * map_size) < (g_num_tetriminos * TET_SIZE))
map_size++;
map = init_map(map_size);
while (!solve_recursive(tetriminos, map))
{
map_size++;
map_delete(map);
map = init_map(map_size);
}
return (map);
}