summary refs log tree commit diff
path: root/sol.c
diff options
context:
space:
mode:
Diffstat (limited to 'sol.c')
-rw-r--r--sol.c170
1 files changed, 40 insertions, 130 deletions
diff --git a/sol.c b/sol.c
index 16a688f..f91310a 100644
--- a/sol.c
+++ b/sol.c
@@ -22,12 +22,11 @@
 #include <time.h>
 
 #include "cards.h"
+#include "layout.h"
 #include "stack.h"
 
 #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
 
-typedef unsigned uint;
-
 enum {
 	Stock,
 	Waste1,
@@ -189,129 +188,47 @@ enum {
 	TableauX = StackMarginX,
 	TableauY = StockY + Cards_Height + StackMarginY,
 
-	StackDeltaX = 2,
-	StackDeltaY = 1,
-
-	Waste3DeltaX = 14,
-	Waste3DeltaY = StackDeltaY,
-
-	TableauDeltaX = 0,
-	TableauDeltaYBack = 3,
-	TableauDeltaYFront = 15,
-
 	WindowWidth = 7 * Cards_Width + 8 * StackMarginX,
 	WindowHeight = 2 * (StackMarginY + Cards_Height)
-		+ 6 * TableauDeltaYBack
-		+ 12 * TableauDeltaYFront
+		+ 6 * FanDownDeltaYBack
+		+ 12 * FanDownDeltaYFront
 		+ StackMarginY,
 };
 
-struct Item {
-	SDL_Rect rect;
-	uint texture;
-	Card card;
-};
-
-struct List {
-	uint len;
-	struct Item items[52];
-};
-
-static void listPush(struct List *list, struct Item item) {
-	assert(list->len < 52);
-	list->items[list->len++] = item;
-}
-
-static struct {
-	SDL_Rect stacks[StacksLen];
-	struct List base;
-	struct List main;
-	struct List drag;
-	struct Item dragItem;
-	uint backTexture;
-} layout;
-
-static struct Item *layoutFind(const SDL_Point *point) {
-	for (uint i = layout.main.len - 1; i < layout.main.len; --i) {
-		if (SDL_PointInRect(point, &layout.main.items[i].rect)) {
-			return &layout.main.items[i];
-		}
-	}
-	return NULL;
-}
-
-static void layoutClear(void) {
-	layout.base.len = 0;
-	layout.main.len = 0;
-	layout.drag.len = 0;
-}
+static const struct Style FanWaste3 = { 1, 14, SquareDeltaY, 14, SquareDeltaY };
 
-static void layoutCard(struct List **list, SDL_Rect *rect, Card card) {
-	if (card == layout.dragItem.card) {
-		*list = &layout.drag;
-		*rect = layout.dragItem.rect;
-	}
-	uint texture = (card > 0 ? (uint)card : layout.backTexture);
-	struct Item item = { *rect, texture, card };
-	listPush(*list, item);
-}
+static struct SDL_Rect stackRects[StacksLen];
+static struct Layout layout;
+static uint backTexture = Cards_Back1;
 
-static void layoutStack(SDL_Rect *rect, const struct Stack *stack, uint depth) {
-	struct List *list = &layout.main;
-	for (uint i = 0; i < stack->len; ++i) {
-		layoutCard(&list, rect, stack->cards[i]);
-		if (i > 0 && i % (depth / 3) == 0) {
-			rect->x += StackDeltaX;
-			rect->y += StackDeltaY;
-		}
-	}
-}
+static void updateLayout(void) {
+	layoutClear(&layout);
 
-static void layoutStock(void) {
-	SDL_Rect rect = { StockX, StockY, Cards_Width, Cards_Height };
-	struct Item item = { rect, Cards_O, 0 };
-	listPush(&layout.base, item);
-	layout.stacks[Stock] = rect;
-	layoutStack(&rect, &stacks[Stock], 24);
-}
+	SDL_Rect stock = { StockX, StockY, Cards_Width, Cards_Height };
+	stackRects[Stock] = stock;
+	listPush(&layout.main, &stock, Cards_O);
+	layoutStack(&layout, &stock, &stacks[Stock], &Square);
 
-static void layoutWaste(void) {
-	SDL_Rect rect = { WasteX, WasteY, Cards_Width, Cards_Height };
-	layoutStack(&rect, &stacks[Waste1], 24);
-	struct List *list = &layout.main;
-	for (uint i = 0; i < stacks[Waste3].len; ++i) {
-		layoutCard(&list, &rect, stacks[Waste3].cards[i]);
-		rect.x += Waste3DeltaX;
-		rect.y += Waste3DeltaY;
-	}
-}
+	SDL_Rect waste = { WasteX, WasteY, Cards_Width, Cards_Height };
+	layoutStack(&layout, &waste, &stacks[Waste1], &Square);
+	layoutStack(&layout, &waste, &stacks[Waste3], &FanWaste3);
 
-static void layoutFoundations(void) {
-	SDL_Rect base = { FoundationX, FoundationY, Cards_Width, Cards_Height };
+	SDL_Rect found = { FoundationX, FoundationY, Cards_Width, Cards_Height };
 	for (uint i = Foundation1; i <= Foundation4; ++i) {
-		struct Item item = { base, Cards_Empty, 0 };
-		listPush(&layout.base, item);
-		layout.stacks[i] = base;
-		SDL_Rect rect = base;
-		layoutStack(&rect, &stacks[i], 13);
-		base.x += Cards_Width + StackMarginX;
+		stackRects[i] = found;
+		listPush(&layout.main, &found, Cards_Empty);
+		SDL_Rect rect = found;
+		layoutStack(&layout, &rect, &stacks[i], &Square);
+		found.x += Cards_Width + StackMarginX;
 	}
-}
 
-static void layoutTableau(void) {
-	SDL_Rect base = { TableauX, TableauY, Cards_Width, Cards_Height };
+	SDL_Rect table = { TableauX, TableauY, Cards_Width, Cards_Height };
 	for (uint i = Tableau1; i <= Tableau7; ++i) {
-		SDL_Rect stack = { base.x, base.y, base.w, WindowHeight };
-		layout.stacks[i] = stack;
-		struct List *list = &layout.main;
-		SDL_Rect rect = base;
-		for (uint j = 0; j < stacks[i].len; ++j) {
-			Card card = stacks[i].cards[j];
-			layoutCard(&list, &rect, card);
-			rect.x += TableauDeltaX;
-			rect.y += (card > 0 ? TableauDeltaYFront : TableauDeltaYBack);
-		}
-		base.x += Cards_Width + StackMarginX;
+		stackRects[i] = table;
+		stackRects[i].h = WindowHeight;
+		SDL_Rect rect = table;
+		layoutStack(&layout, &rect, &stacks[i], &FanDown);
+		table.x += Cards_Width + StackMarginX;
 	}
 }
 
@@ -320,10 +237,10 @@ static bool keyDown(SDL_KeyboardEvent key) {
 		case SDLK_F2: gameDeal(); return true;
 		case SDLK_BACKSPACE: return gameUndo();
 		case SDLK_b: {
-			layout.backTexture -= Cards_Back1;
-			layout.backTexture += 1;
-			layout.backTexture %= 12;
-			layout.backTexture += Cards_Back1;
+			backTexture -= Cards_Back1;
+			backTexture += 1;
+			backTexture %= 12;
+			backTexture += Cards_Back1;
 			return true;
 		}
 		case SDLK_d: {
@@ -337,11 +254,11 @@ static bool keyDown(SDL_KeyboardEvent key) {
 
 static bool mouseButtonDown(SDL_MouseButtonEvent button) {
 	struct SDL_Point point = { button.x, button.y };
-	if (SDL_PointInRect(&point, &layout.stacks[Stock])) {
+	if (SDL_PointInRect(&point, &stackRects[Stock])) {
 		gameDraw();
 		return true;
 	}
-	struct Item *item = layoutFind(&point);
+	struct Item *item = listFind(&layout.main, &point);
 	if (!item) return false;
 	if (!gameAvail(item->card)) return gameReveal(item->card);
 	if (button.clicks % 2 == 0) {
@@ -358,7 +275,7 @@ static bool mouseButtonUp(SDL_MouseButtonEvent button) {
 	(void)button;
 	if (!layout.dragItem.card) return false;
 	for (uint dest = 0; dest < StacksLen; ++dest) {
-		if (SDL_HasIntersection(&layout.dragItem.rect, &layout.stacks[dest])) {
+		if (SDL_HasIntersection(&layout.dragItem.rect, &stackRects[dest])) {
 			if (gameMove(dest, layout.dragItem.card)) break;
 		}
 	}
@@ -379,11 +296,9 @@ static SDL_Texture *textures[Cards_Count];
 
 static void renderList(const struct List *list) {
 	for (uint i = 0; i < list->len; ++i) {
-		SDL_RenderCopy(
-			render,
-			textures[list->items[i].texture],
-			NULL, &list->items[i].rect
-		);
+		int tex = list->items[i].card;
+		if (tex < 0) tex = backTexture;
+		SDL_RenderCopy(render, textures[tex], NULL, &list->items[i].rect);
 	}
 }
 
@@ -451,19 +366,14 @@ int main(void) {
 	Cards_Free(cards);
 
 	srand(time(NULL));
-	layout.backTexture = Cards_Back1 + randUniform(12);
+	backTexture = Cards_Back1 + randUniform(12);
 	gameDeal();
 
 	for (;;) {
-		layoutClear();
-		layoutStock();
-		layoutWaste();
-		layoutFoundations();
-		layoutTableau();
+		updateLayout();
 
 		SDL_SetRenderDrawColor(render, 0x00, 0xAA, 0x55, 0xFF);
 		SDL_RenderClear(render);
-		renderList(&layout.base);
 		renderList(&layout.main);
 		renderList(&layout.drag);
 		SDL_RenderPresent(render);