From 1dbfd68878551ddc420907cb57bcf2f49af56d26 Mon Sep 17 00:00:00 2001
From: quenousimporte <quenousimporte@git.ouvaton.coop>
Date: Sat, 12 Apr 2025 13:03:50 +0200
Subject: [PATCH] maze generation with dfs algo

---
 w/w.c | 192 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 150 insertions(+), 42 deletions(-)

diff --git a/w/w.c b/w/w.c
index bae4347..3b2f0a8 100644
--- a/w/w.c
+++ b/w/w.c
@@ -41,6 +41,7 @@
 #define TILE_START   's'
 #define TILE_UNKNOWN '?'
 #define TILE_UNUSED  '.'
+#define TILE_UNVISITED  'x'
 
 #define ITEM_POTION  '0'
 #define ITEM_TRUC    '1'
@@ -75,7 +76,7 @@ typedef struct {
 
 typedef struct {
 	Character hero;
-	Position position;	
+	Position position;
 	Item inventory[INVENTORY_SIZE];
 	char screen;
 } Gamestate;
@@ -89,9 +90,8 @@ Character currentmonster;
 Round* firstround = NULL;
 Round* currentround = NULL;
 
-int freedom = 2;
 char map[MAP_SIZE * MAP_SIZE];
-
+int ddl;
 Character monsters[2] = {
 	{ "alien bleu", 2, 2, 1, 1 },
 	{ "vilaine araignée", 5, 8, 2, 1 }
@@ -146,7 +146,7 @@ void drawmap()
 		}
 		printf("\n");
 	}
-	printf("freedom: %d\n", freedom);
+	printf("ddl=%d\n", ddl);
 }
 
 void drawpov3d()
@@ -330,26 +330,6 @@ void update3dpov()
 
 void updatepov()
 {
-	// generate map
-	/*setatpos(state.position.x, state.position.y, ' ');
-	
-	Position front;
-	memcpy(&front, &state.position, sizeof(Position));
-	if (state.position.orientation 
-	
-	// right
-	if (state.position.x + 1 == 0)
-	{
-		setatpos(state.position.x + 1, state.position.y, 'w');
-	}
-	else if (charatpos(state.position.x + 1, state.position.y) == '?')
-	{
-		char c = dice() > 3 ? 'w' : ' ';
-		setatpos(state.position.x + 1, state.position.y, c);
-		if (c == 'w') freedom--;
-	}*/
-	
-	
 	int x = state.position.x;
 	int y = state.position.y;
 	char orientation = state.position.orientation;
@@ -500,7 +480,7 @@ void createhero(char* name)
 	state.hero.gold = 0;
 	state.hero.atk = 1;
 	state.hero.def = 1;
-	
+
 	Item potion = { ITEM_POTION, "potion", 20, 0 };
 	Item truc = { ITEM_TRUC, "truc", 2000, 0 };
 	state.inventory[0] = potion;
@@ -587,27 +567,153 @@ void drawrounds()
 	}
 }
 
-char gentile()
+char gentile(int x, int y)
 {
-	int r = dice();
-	if (r == 1) return 'd';
-	if (r < 4) return 'w';
-	return ' ';
+	char c = charatpos(x, y);
+	if (c == TILE_UNKNOWN)
+	{
+		int d = dice();
+		if (d == 1)
+		{
+			c = TILE_DOOR;
+			ddl++;
+		}
+		else if (d < 5 && ddl > 1)
+		{
+			c = TILE_WALL;
+			ddl--;
+		}
+		else
+		{
+			c = TILE_FREE;
+			ddl++;
+		}
+		setatpos(x, y, c);
+	}
+	return TILE_UNUSED;
+}
+
+void updatemap()
+{
+	int x = state.position.x;
+	int y = state.position.y;
+
+	// north
+	char c = gentile(x, y - 1);
+	if (c == TILE_FREE)
+	{
+		ddl--;
+		gentile(x - 1, y - 2);
+		gentile(x + 1, y - 2);
+	}
+
+	// south
+	c = gentile(x, y + 1);
+	if (c == TILE_FREE)
+	{
+		ddl--;
+		gentile(x - 1, y + 2);
+		gentile(x + 1, y + 2);
+	}
+
+	// east
+	c = gentile(x + 1, y);
+	if (c == TILE_FREE)
+	{
+		ddl--;
+		gentile(x + 2, y - 1);
+		gentile(x + 2, y + 1);
+	}
+
+	// west
+	c = gentile(x - 1, y);
+	if (c == TILE_FREE)
+	{
+		ddl--;
+		gentile(x - 2, y - 1);
+		gentile(x - 2, y + 1);
+	}
+}
+
+void dfs(int x, int y)
+{
+	setatpos(x, y, TILE_FREE);
+
+	bool nok = false;
+	bool eok = false;
+	bool sok = false;
+	bool wok = false;
+
+	while (! (nok && eok && sok && wok))
+	{
+		char orientation = rand() % 4;
+		switch (orientation)
+		{
+		case NORTH:
+			nok = true;
+			if (charatpos(x, y - 2) == TILE_UNVISITED)
+			{
+				setatpos(x, y - 1, dice() == 6 ? TILE_DOOR : TILE_FREE);
+				dfs(x, y - 2);
+			}
+			break;
+		case SOUTH:
+			sok = true;
+			if (charatpos(x, y + 2) == TILE_UNVISITED)
+			{
+				setatpos(x, y + 1, dice() == 6 ? TILE_DOOR : TILE_FREE);
+				dfs(x, y + 2);
+			}
+			break;
+		case EAST:
+			eok = true;
+			if (charatpos(x - 2, y) == TILE_UNVISITED)
+			{
+				setatpos(x - 1, y, dice() == 6 ? TILE_DOOR : TILE_FREE);
+				dfs(x - 2, y);
+			}
+			break;
+		case WEST:
+			wok = true;
+			if (charatpos(x + 2, y) == TILE_UNVISITED)
+			{
+				setatpos(x + 1, y, dice() == 6 ? TILE_DOOR : TILE_FREE);
+				dfs(x + 2, y);
+			}
+			break;
+		}
+	}
 }
 
 void initmap()
 {
-	memset(&map, TILE_UNKNOWN, MAP_SIZE * MAP_SIZE); 
-	setatpos(1, 13, TILE_FREE);
+	//memset(&map, TILE_UNKNOWN, MAP_SIZE * MAP_SIZE);
+	memset(&map, TILE_WALL, MAP_SIZE * MAP_SIZE);  // dfs: put walls everywhere
+
+	// dfs: add random room
+	for (int x = 0; x < MAP_SIZE; x ++)
+		for (int y = 0; y < MAP_SIZE; y++)
+			if (dice() > 4)
+				// setatpos(x, y, TILE_FREE);
 
-	setatpos(0, 13, TILE_WALL);
-	setatpos(0, 11, TILE_WALL);
-	setatpos(1, 14, TILE_WALL);
-	setatpos(3, 14, TILE_WALL);
-	
 	for (int x = 0; x < MAP_SIZE; x += 2)
+	{
 		for (int y = 14; y >=0; y -= 2)
-			setatpos(x, y, TILE_UNUSED);
+		{
+			setatpos(0, y - 1, TILE_WALL);
+			setatpos(14, y - 1, TILE_WALL);
+
+			setatpos(x, y, TILE_WALL); // => instead of TILE_UNUSED, for readibility
+
+			//setatpos(x + 1, y + 1, TILE_FREE);
+			setatpos(x + 1, y + 1, TILE_UNVISITED); // dfs
+		}
+		setatpos(x + 1, 0, TILE_WALL);
+		setatpos(x + 1, 14, TILE_WALL);
+	}
+
+	// setatpos(1, 13, TILE_FREE);
+	dfs(1,13);
 }
 
 void update(char* command)
@@ -622,9 +728,10 @@ void update(char* command)
 			int x = state.position.x;
 			int y = state.position.y;
 			forward();
+			//updatemap();
 			if ( (x != state.position.x || y != state.position.y) && dice() > 4)
 			{
-				gotomonster();
+				// gotomonster();
 			}
 			break;
 		case CMD_RIGHT:
@@ -667,8 +774,9 @@ void update(char* command)
 			state.position.x = 1;
 			state.position.y = 13;
 			state.position.orientation = NORTH;
-			
+
 			initmap();
+			//updatemap();
 			updatepov();
 		}
 		else if (c == CMD_GOTOMARKET)
@@ -792,8 +900,8 @@ void draw()
 	else if (state.screen == SC_MAP)
 	{
 		update3dpov();
-		//drawpov3d();
 		drawmap();
+		drawpov3d();
 
 		if (charatpos(state.position.x, state.position.y) == TILE_START)
 		{
@@ -844,7 +952,7 @@ void draw()
 			printf("price: %d\n", item.price);
 			printf("owned: %d\n", item.count);
 		}
-		
+
 		printf("\nr: Retour à la station\n");
 	}