#include #include #include #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); }