summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--sol.c116
1 files changed, 94 insertions, 22 deletions
diff --git a/sol.c b/sol.c
index 3a289b9..f0d9616 100644
--- a/sol.c
+++ b/sol.c
@@ -106,19 +106,47 @@ enum {
 		+ StackMarginY,
 };
 
-static SDL_Renderer *render;
-static SDL_Texture *textures[Cards_Count];
+struct Item {
+	SDL_Rect rect;
+	uint tex;
+	Sint8 card;
+};
+
+struct Layout {
+	uint len;
+	struct Item items[52];
+};
+
+static void layoutClear(struct Layout *list) {
+	list->len = 0;
+}
+static void layoutPush(struct Layout *list, struct Item item) {
+	assert(list->len < 52);
+	list->items[list->len++] = item;
+}
+
+static struct {
+	struct Layout base;
+	struct Layout main;
+	struct Layout drag;
+	struct Item dragItem;
+} layout;
 
 static uint cardBack = Cards_Back1;
 
-static void renderCard(const SDL_Rect *rect, Sint8 card) {
-	uint i = (card > 0 ? card : cardBack);
-	SDL_RenderCopy(render, textures[i], NULL, rect);
+static void layoutCard(struct Layout **list, SDL_Rect *rect, Sint8 card) {
+	if (card == layout.dragItem.card) {
+		*list = &layout.drag;
+		*rect = layout.dragItem.rect;
+	}
+	struct Item item = { *rect, (card > 0 ? card : cardBack), card };
+	layoutPush(*list, item);
 }
 
-static void renderStack(SDL_Rect *rect, const struct Stack *stack, uint depth) {
+static void layoutStack(SDL_Rect *rect, const struct Stack *stack, uint depth) {
+	struct Layout *list = &layout.main;
 	for (uint i = 0; i < stack->len; ++i) {
-		renderCard(rect, stack->cards[i]);
+		layoutCard(&list, rect, stack->cards[i]);
 		if (i > 0 && i % (depth / 3) == 0) {
 			rect->x += StackDeltaX;
 			rect->y += StackDeltaY;
@@ -126,39 +154,43 @@ static void renderStack(SDL_Rect *rect, const struct Stack *stack, uint depth) {
 	}
 }
 
-static void renderStock(void) {
+static void layoutStock(void) {
 	SDL_Rect rect = { StockX, StockY, Cards_Width, Cards_Height };
-	SDL_RenderCopy(render, textures[Cards_O], NULL, &rect);
-	renderStack(&rect, &stacks[Stock], 24);
+	struct Item item = { rect, Cards_O, 0 };
+	layoutPush(&layout.base, item);
+	layoutStack(&rect, &stacks[Stock], 24);
 }
 
-static void renderWaste(void) {
+static void layoutWaste(void) {
 	SDL_Rect rect = { WasteX, WasteY, Cards_Width, Cards_Height };
-	renderStack(&rect, &stacks[Waste1], 24);
+	layoutStack(&rect, &stacks[Waste1], 24);
+	struct Layout *list = &layout.main;
 	for (uint i = 0; i < stacks[Waste3].len; ++i) {
-		renderCard(&rect, stacks[Waste3].cards[i]);
+		layoutCard(&list, &rect, stacks[Waste3].cards[i]);
 		rect.x += Waste3DeltaX;
 		rect.y += Waste3DeltaY;
 	}
 }
 
-static void renderFoundations(void) {
+static void layoutFoundations(void) {
 	SDL_Rect base = { FoundationX, FoundationY, Cards_Width, Cards_Height };
 	for (uint i = Foundation1; i <= Foundation4; ++i) {
+		struct Item item = { base, Cards_Empty, 0 };
+		layoutPush(&layout.base, item);
 		SDL_Rect rect = base;
-		SDL_RenderCopy(render, textures[Cards_Empty], NULL, &rect);
-		renderStack(&rect, &stacks[i], 13);
+		layoutStack(&rect, &stacks[i], 13);
 		base.x += Cards_Width + StackMarginX;
 	}
 }
 
-static void renderTableau(void) {
+static void layoutTableau(void) {
 	SDL_Rect base = { TableauX, TableauY, Cards_Width, Cards_Height };
 	for (uint i = Tableau1; i <= Tableau7; ++i) {
+		struct Layout *list = &layout.main;
 		SDL_Rect rect = base;
 		for (uint j = 0; j < stacks[i].len; ++j) {
 			Sint8 card = stacks[i].cards[j];
-			renderCard(&rect, card);
+			layoutCard(&list, &rect, card);
 			rect.x += TableauDeltaX;
 			rect.y += (card > 0 ? TableauDeltaYFront : TableauDeltaYBack);
 		}
@@ -166,6 +198,19 @@ static void renderTableau(void) {
 	}
 }
 
+static SDL_Renderer *render;
+static SDL_Texture *textures[Cards_Count];
+
+static void renderLayout(const struct Layout *list) {
+	for (uint i = 0; i < list->len; ++i) {
+		SDL_RenderCopy(
+			render,
+			textures[list->items[i].tex],
+			NULL, &list->items[i].rect
+		);
+	}
+}
+
 static void err(const char *prefix) {
 	fprintf(stderr, "%s: %s\n", prefix, SDL_GetError());
 	exit(EXIT_FAILURE);
@@ -238,13 +283,40 @@ int main(void) {
 			}
 		}
 
+		if (event.type == SDL_MOUSEBUTTONDOWN) {
+			struct SDL_Point point = { event.button.x, event.button.y };
+			for (uint i = layout.main.len - 1; i < layout.main.len; --i) {
+				if (SDL_PointInRect(&point, &layout.main.items[i].rect)) {
+					layout.dragItem = layout.main.items[i];
+					break;
+				}
+			}
+		}
+
+		if (event.type == SDL_MOUSEBUTTONUP) {
+			layout.dragItem.card = 0;
+		}
+
+		if (event.type == SDL_MOUSEMOTION && event.motion.state) {
+			layout.dragItem.rect.x += event.motion.xrel;
+			layout.dragItem.rect.y += event.motion.yrel;
+		}
+
+		layoutClear(&layout.base);
+		layoutClear(&layout.main);
+		layoutClear(&layout.drag);
+
+		layoutStock();
+		layoutWaste();
+		layoutFoundations();
+		layoutTableau();
+
 		SDL_SetRenderDrawColor(render, 0x00, 0xAA, 0x55, 0xFF);
 		SDL_RenderClear(render);
 
-		renderStock();
-		renderWaste();
-		renderFoundations();
-		renderTableau();
+		renderLayout(&layout.base);
+		renderLayout(&layout.main);
+		renderLayout(&layout.drag);
 
 		SDL_RenderPresent(render);
 	}