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
|
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "pieces.h"
#include "util.h"
const int N_SHAPES = 17;
const struct piece SHAPES[] = {
{1, 1, 1, "+"},
{1, 2, 2, "++"},
{1, 3, 3, "+++"},
{1, 4, 4, "++++"},
{1, 5, 5, "+++++"},
{2, 2, 2, "+ +"}, // 2x2 diagonal
{2, 2, 4, "++++"}, // 2x2 square
{2, 3, 4, "++++ "}, // L shape
{2, 3, 4, "++ ++"}, // Z shape
{2, 3, 4, "+++ + "}, // T shape
{2, 3, 6, "++++++"}, // 2x3 rectangle
{2, 4, 5, "+++++ "}, // long L shape
{2, 4, 8, "++++++++"}, // 2x4 rectangle
{3, 3, 5, "++++ + "}, // large L shape
{3, 3, 5, "+++ + + "}, // large T shape
{3, 3, 3, "+ + +"}, // 3x3 diagonal
{3, 3, 9, "+++++++++"}, // 3x3 square
};
void transpose(struct piece* pc) {
// transpose blocks
char* old = malloc(strlen(pc->blocks) + 1);
if (old == NULL)
mallocfail();
strcpy(old, pc->blocks); // before transposition
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
pc->blocks[c * (pc->h) + r] = old[r * (pc->w) + c];
}
}
free(old);
// swap dimensions
int h = pc->h;
pc->h = pc->w;
pc->w = h;
}
void rotate(struct piece* pc) {
// rotate `pc` ccw by 90 degrees
// transpose blocks
char* old = malloc(strlen(pc->blocks) + 1);
if (old == NULL)
mallocfail();
strcpy(old, pc->blocks); // before transposition
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
pc->blocks[(pc->w - c - 1) * (pc->h) + r] = old[r * (pc->w) + c];
}
}
free(old);
// swap dimensions
int h = pc->h;
pc->h = pc->w;
pc->w = h;
}
struct piece* randpiece() {
// select a random shape from `SHAPES`, make a copy where memory for `.blocks` is manually managed,
// then do random transformations to the copy
struct piece shape = SHAPES[rand() % N_SHAPES];
char* blocks = malloc(strlen(shape.blocks) + 1);
if (blocks == NULL)
mallocfail();
strcpy(blocks, shape.blocks);
struct piece* pc = malloc(sizeof(struct piece));
if (pc == NULL)
mallocfail();
pc->h = shape.h;
pc->w = shape.w;
pc->points = shape.points;
pc->blocks = blocks;
if (rand() % 2) transpose(pc);
for (int i = rand() % 4; i > 0; i--) // 0 to 3 times
rotate(pc);
return pc;
}
void refillpieces(struct piece** hand, int nhand) {
// randomly select `nhand` pieces to `hand`
for (int i = 0; i < nhand; i++) {
hand[i] = randpiece();
}
}
bool placeable(char* map, struct piece* pc, int row, int col, int mapH, int mapW) {
// boundary check
if (row < 0 || row + (pc->h) > mapH || col < 0 || col + (pc->w) > mapW)
return false;
// check if blocks to be taken by `pc` are vacant
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
if (map[(row + r) * mapW + col + c] == '+' && pc->blocks[r * pc->w + c] == '+')
return false;
}
}
return true;
}
void place(char* map, struct piece* pc, int row, int col, int mapW) {
for (int r = 0; r < pc->h; r++) {
for (int c = 0; c < pc->w; c++) {
if (pc->blocks[r * (pc->w) + c] == '+')
map[(row + r) * mapW + col + c] = '+';
}
}
}
void freepiece(struct piece* pc) {
free(pc->blocks);
free(pc);
}
|