shithub: scoundrel

Download patch

ref: fcdcc0d9929f461f09f35bf901e3344c89b4efc5
parent: 2f7ec64f856564b48d3ae7493fae937afe29c794
author: sirjofri <sirjofri@sirjofri.de>
date: Fri Feb 13 19:12:13 EST 2026

first working gameplay

--- a/dat.h
+++ b/dat.h
@@ -16,4 +16,6 @@
 	
 	int running;
 	int canskip;
+	
+	int hadpotion;
 };
\ No newline at end of file
--- a/game.c
+++ b/game.c
@@ -8,10 +8,138 @@
 struct Card {
 	Color col;
 	int value;
+	Card *next;
 };
 
 State state;
 
+Card possible[4*9 + 2*4];
+
+Card *deck = nil;
+Card *last = nil;
+int ncards = 0;
+
+static void
+addcard(int c, Color col)
+{
+	Card *card;
+	card = mallocz(sizeof(Card), 1);
+	if (!card)
+		sysfatal("mallocz: %r");
+	card->col = col;
+	card->value = c;
+	
+	if (!deck) {
+		deck = last = card;
+		state.deckcards++;
+		return;
+	}
+	
+	last->next = card;
+	last = card;
+	state.deckcards++;
+}
+
+static Card
+drawcard(void)
+{
+	Card *c, card;
+	if (!deck)
+		return (Card){-1, -1, nil};
+	c = deck;
+	deck = deck->next;
+	card = *c;
+	free(c);
+	state.deckcards--;
+	return card;
+}
+
+static int
+cardexists(int c, Color col)
+{
+	Card *cd;
+	
+	for (cd = deck; cd; cd = cd->next) {
+		if (cd->col == col && cd->value == c)
+			return 1;
+	}
+	return 0;
+}
+
+static void
+cleardeck(void)
+{
+	Card *c, *d;
+	
+	for (c = deck; c; c = d) {
+		d = c->next;
+		free(c);
+	}
+	deck = last = nil;
+	state.deckcards = 0;
+}
+
+static int
+validcard(int c, Color col)
+{
+	int range;
+	
+	if (c < 2)
+		return 0;
+	
+	switch (col) {
+	case Diamonds:
+	case Hearts:
+		range = 10;
+		break;
+	case Clubs:
+	case Spades:
+		range = 14;
+		break;
+	default:
+		return 0;
+	}
+	return c <= range;
+}
+
+static void
+gendeck(void)
+{
+	int c, col;
+	int expected = 4*9 + 2*4;
+	cleardeck();
+	
+	while (state.deckcards < expected) {
+		c = nrand(13) + 2;
+		col = nrand(4);
+		if (!validcard(c, col))
+			continue;
+		if (cardexists(c, col))
+			continue;
+		addcard(c, col);
+	}
+}
+
+static void
+fillroom(void)
+{
+	int i;
+	Card c;
+	
+	for (i = 0; i < 4; i++) {
+		if (state.room[i] > 0)
+			continue;
+		c = drawcard();
+		if (c.value < 0) {
+			fprint(2, "error: drawcard. Empty deck?\n");
+			continue;
+		}
+		state.room[i] = c2n(c.value, c.col);
+	}
+	
+	state.hadpotion = 0;
+}
+
 int
 c2n(int c, Color col)
 {
@@ -18,6 +146,15 @@
 	return c + col*15;
 }
 
+static Card
+n2c(int n)
+{
+	Card c;
+	c.col = n/15;
+	c.value = n%15;
+	return c;
+}
+
 State*
 getstate()
 {
@@ -27,16 +164,54 @@
 int
 roomaction(int c, int useweapon)
 {
-	int card;
+	int cd, i, n;
+	Card card, weapon;
 	
 	if (!state.running)
 		return 0;
 	
-	card = state.room[c];
-	if (card < 0)
+	cd = state.room[c];
+	if (cd < 0)
 		return 0;
-	// TODO: manage card: fight if enemy, heal if potion, change weapon if weapon card
-	fprint(2, "card pressed: %d\n", c);
+	
+	card = n2c(cd);
+	weapon = n2c(state.weapon);
+	
+	switch (card.col) {
+	case Diamonds:
+		state.lastweaponkill = -1;
+		state.weapon = cd;
+		state.room[c] = -1;
+		break;
+	case Hearts:
+		state.room[c] = -1;
+		if (state.hadpotion)
+			break;
+		state.hp += card.value;
+		if (state.hp > 20) state.hp = 20;
+		state.hadpotion = 1;
+		break;
+	case Spades:
+	case Clubs:
+		state.room[c] = -1;
+		state.hp -= useweapon && weapon.value > 0 ? card.value - weapon.value : card.value;
+		if (useweapon)
+			state.lastweaponkill = cd;
+		break;
+	}
+	
+	state.canskip = 0;
+	
+	n = 0;
+	for (i = 0; i < 4; i++) {
+		if (state.room[i] < 0)
+			n++;
+	}
+	if (n >= 3) {
+		state.canskip = 1;
+		fillroom();
+	}
+	
 	return 1;
 }
 
@@ -43,6 +218,7 @@
 int
 startgame(void)
 {
+	int i;
 	if (state.running)
 		return 0;
 	
@@ -50,17 +226,14 @@
 	
 	state.canskip = 1;
 	state.hp = 20;
-	// TODO: mix cards, update state
+	state.weapon = -1;
+	state.lastweaponkill = -1;
 	
-	// fake display
+	gendeck();
 	
-	state.room[0] = c2n(2, Spades);
-	state.room[1] = c2n(11, Diamonds);
-	state.room[2] = c2n(14, Clubs);
-	state.room[3] = c2n(4, Hearts);
-	state.deckcards = 5;
-	state.weapon = c2n(6, Diamonds);
-	state.lastweaponkill = c2n(4, Spades);
+	for (i = 0; i < 4; i++)
+		state.room[i] = -1;
+	fillroom();
 	return 1;
 }
 
@@ -67,12 +240,27 @@
 int
 nextround(void)
 {
+	int i;
+	Card c;
 	if (!state.running)
 		return 0;
 	if (!state.canskip)
 		return 0;
 	
+	/* skipped this round, another skip is invalid! */
 	state.canskip = 0;
-	// TODO: skip round: move cards to end of deck
+	
+	for (i = 0; i < 4; i++) {
+		if (state.room[i] < 0) {
+			fprint(2, "skip room with empty slot. Invalid!\n");
+			continue;
+		}
+		c = n2c(state.room[i]);
+		addcard(c.value, c.col);
+		state.room[i] = -1;
+	}
+	
+	fillroom();
+	
 	return 1;
 }
\ No newline at end of file
--- a/main.c
+++ b/main.c
@@ -192,6 +192,7 @@
 		sysfatal("initdraw: %r");
 	
 	einit(Emouse|Ekeyboard);
+	srand(time(0));
 	
 	loadimages("img");
 	
--