diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | pieces.c | 75 | ||||
-rw-r--r-- | pieces.h | 11 | ||||
-rw-r--r-- | sirtet.c | 136 |
5 files changed, 234 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed1f490 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.undodir/ +sirtet diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..97bcb23 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +all: compile run + +compile: + gcc -g sirtet.c pieces.c -o sirtet + +run: + ./sirtet + +valgrind: + valgrind --leak-check=full --show-leak-kinds=all ./sirtet diff --git a/pieces.c b/pieces.c new file mode 100644 index 0000000..95c9923 --- /dev/null +++ b/pieces.c @@ -0,0 +1,75 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "pieces.h" + +const int N_SHAPES = 17; +const struct piece SHAPES[] = { + {1, 1, "+"}, + {1, 2, "++"}, + {1, 3, "+++"}, + {1, 4, "++++"}, + {1, 5, "+++++"}, + {2, 2, "+ +"}, // 2x2 diagonal + {2, 2, "++++"}, // 2x2 square + {2, 3, "++++ "}, // L shape + {2, 3, "++ ++"}, // Z shape + {2, 3, "+++ + "}, // T shape + {2, 3, "++++++"}, // 2x3 rectangle + {2, 4, "+++++ "}, // long L shape + {2, 4, "++++++++"}, // 2x4 rectangle + {3, 3, "++++ + "}, // large L shape + {3, 3, "+++ + + "}, // large T shape + {3, 3, "+ + +"}, // 3x3 diagonal + {3, 3, "+++++++++"}, // 3x3 square +}; + +void transpose(struct piece* pc) { + // transpose blocks + char* old = malloc(strlen(pc->blocks) + 1); + 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); + 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); + strcpy(blocks, shape.blocks); + struct piece* pc = malloc(sizeof(struct piece)); + pc->h = shape.h; + pc->w = shape.w; + pc->blocks = blocks; + if (rand() % 2) transpose(pc); + for (int i = rand() % 4; i > 0; i--) // 0 to 3 times + rotate(pc); + return pc; +} + diff --git a/pieces.h b/pieces.h new file mode 100644 index 0000000..ee2e371 --- /dev/null +++ b/pieces.h @@ -0,0 +1,11 @@ +#ifndef PIECES_H +#define PIECES_H +struct piece { + int h; + int w; + char* blocks; +}; + +struct piece* randpiece(); +#endif + diff --git a/sirtet.c b/sirtet.c new file mode 100644 index 0000000..94ca5a1 --- /dev/null +++ b/sirtet.c @@ -0,0 +1,136 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <time.h> +#include "pieces.h" + +void printmap(char** map, int nrow, int ncol) { + printf(" "); + for (int c = 0; c < ncol; c++) { + printf("-"); + } + printf("\n"); + for (int r = 0; r < nrow; r++) { + printf("|"); + for (int c = 0; c < ncol; c++) { + printf("%c", map[r][c]); + } + printf("|\n"); + } + printf(" "); + for (int c = 0; c < ncol; c++) { + printf("-"); + } + printf("\n"); +} + +void printpieces(struct piece** hand, int nhand) { + for (int i = 0; i < nhand; i++) { + printf("Piece %d\n", i); + struct piece* pc = hand[i]; + for (int r = 0; r < pc->h; r++) { + for (int c = 0; c < pc->w; c++) { + printf("%c", pc->blocks[r * pc->w + c]); + } + printf("\n"); + } + printf("\n"); + } +} + +void clearmap(char** map, int nrow, int ncol) { + for (int r = 0; r < nrow; r++) { + for (int c = 0; c < ncol; c++) { + map[r][c] = ' '; + } + } +} + +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][col + c] == '+' && pc->blocks[r * pc->w + c] == '+') + return false; + } + } + + return true; +} + +void place(char** map, struct piece* pc, int row, int col) { + 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][col + c] = '+'; + } + } +} + +void freepieces(struct piece** hand, int nhand) { + for (int i = 0; i < nhand; i++) { + free(hand[i]->blocks); + free(hand[i]); + } +} + +void refillpieces(struct piece** hand, int nhand) { + // randomly select `no` pieces from `pool` to `hand` + // capacities of `hand` and `pool` are `nhand` and `npool` resp. + for (int i = 0; i < nhand; i++) { + hand[i] = randpiece(); + } +} + +void sirtet() { + const int H = 8; // canvas height + const int W = 8; // canvas width + const int P = 3; // maximum # of pieces at hand + + // init memory and game state + char** map = malloc(H * sizeof(char*)); + for (int r = 0; r < H; r++) { + map[r] = malloc(W * sizeof(char)); + } + struct piece** hand = malloc(P * sizeof(struct piece*)); + int pieces_left = P; + srand(time(NULL)); + clearmap(map, H, W); + + bool over = false; + refillpieces(hand, P); + + // begin game loop + while (!over) { + printmap(map, H, W); + printpieces(hand, P); + // await user input + int pc_idx; + int row; + int col; + printf("Input [piece #] [row #] [col #]: "); + scanf("%d %d %d", &pc_idx, &row, &col); + while (pc_idx < 0 || pc_idx >= P || !placeable(map, hand[pc_idx], row, col, H, W)) { + printf("You cannot do that. Try again: "); + scanf("%d %d %d", &pc_idx, &row, &col); + } + place(map, hand[pc_idx], row, col); + } + + // free memory + freepieces(hand, P); + for (int r = 0; r < H; r++) { + free(map[r]); + } + free(map); + free(hand); +} + +int main(int argc, char *argv[]) { + sirtet(); + return 0; +} |