summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile10
-rw-r--r--pieces.c75
-rw-r--r--pieces.h11
-rw-r--r--sirtet.c136
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;
+}