|
![]() |
#1 | ||
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Join Date: May 2005
Location: Aurora, United States
Posts: 606
|
![]() Hey, 13 out of 40 in a competition where no morons are allowed isn't bad. You were doing well just to get in.
3DMaze This is a real cool one. Taken from yet another entry in the International Obvscated C-Code Contest (another exelent place to find C-Code examples written by people better than me). Sean Barrett's winning 1991 entry drew an ascii representation of a first person view through a maze. For the maze the program read it's own code in and used the whitespaces for floor. Clever, but not very dynamic. So I decided to make a random maze generator and attach it to the drawing algorithm. This meant I had to take code that was not formatted for reading and reformat it with variables with understandable names and everything. It was an interesting way to figure out how this extremely clever routine worked. The final result is uber-cool and looks like this: Code:
****\****************************************** / **** |**************************************** | **** |**************************************** | **** |**************************************** | **** |**************************************** | **** |--------\********************** /--------| **** |****** |**\****************** /**|****** | **** |****** |****\************** /****|****** | **** |****** |**** |************/|**** |****** | **** |****** |**** |**********/**|**** |****** | **** |****** |**** |---------|** |**** |****** | **** |****** |**** |** |**** |** |**** |****** | **** |****** |**** |---------|** |**** |****** | **** |****** |**** |**********\**|**** |****** | **** |****** |**** |************\|**** |****** | **** |****** |****/************** \****|****** | **** |****** |**/****************** \**|****** | **** |--------/********************** \--------| **** |**************************************** | **** |**************************************** | **** |**************************************** | **** |**************************************** | ****/****************************************** \ (F)orward, (L)eft or (R)ight? Code:
/* 3DMaze * by Joseph Larson 2005 * Maze generator written by Joseph Larson * 3D drawing routine by Sean Barrett 1991, found at the International * Obfuscated C Code Contest http://www.ioccc.org */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <ctype.h> #include <string.h> #include <math.h> #define XMAX 39 #define YMAX 11 #define MID 26 #define WALL 0 #define UNSEEN 1 #define SEEN 2 #define TRAVL 3 #define EXIT -1 #define D(a) (2 * (a + 1)) #define NP(a, b) (a * (b - 1) + (a - 1) * b) #define SWAP(a,b) a ^= b; b ^= a; a ^= b #define X(a) xytable[(a) % 4] #define Y(a) xytable[(a + 1) % 4] int scale[6] = {11, 10, 6, 3, 1, 0}; int xytable[4] = {1, 0, -1, 0}; int maze[D(XMAX)][D(YMAX)], xsize, ysize, x, y, face, hpos; void drawmap (void) { **int c, d; **for (d = 2 * ysize; d >= 0; d--) { ****putchar ('\n'); ****for (c = 1; c < D(xsize); c++) ******putchar ((c == x && d == y) ? '*' : "## ."[maze[c][d]]); **} } void snr (int n1, int n2) { /* search and replace */ **int c, d; **if (n1) ****for (c = 2; c < D(xsize); c++) for (d = 1; d < D(ysize) - 1; d++) ******if (maze[c][d] == n1) maze[c][d] = n2; } void generate (void) { **int px[NP(XMAX, YMAX)], py[NP(XMAX, YMAX)], b, c, d; **for (c = 0; c < D(XMAX); c++) for (d = 0; d < D(YMAX); d++) ****maze[c][d] = (c) ? WALL : EXIT; **b = 0; **/* populate potentials */ **for (c = 3; c < 2 * xsize; c += 2) for (d = 1; d < 2 * ysize; d += 2) { ****px[b] = c; py[b++] = d; **} **for (c = 2; c <= 2 * xsize; c += 2) for (d = 2; d < 2 * ysize; d += 2) { ****px[b] = c; py[b++] = d; **} **/* randomize potentials */ **for (b = 0; b < NP(xsize, ysize); b++) { ****c = rand () % NP(xsize, ysize); ****if (c - b) {SWAP (px[c], px[b]); SWAP (py[c], py[b]);} **} **/* make the maze */ **for (b = 0; b < NP(xsize, ysize); b++) { ****c = d = 0; ****if (py[b] % 2) c = 1; else d = 1; ****if (!maze[px[b] + c][py[b] + d] || !maze[px[b] - c][py[b] - d] ******|| maze[px[b] + c][py[b] + d] != maze[px[b] - c][py[b] - d]) { ******snr (maze[px[b] + c][py[b] + d], b + 1); ******snr (maze[px[b] - c][py[b] - d], b + 1); ******maze[px[b]][py[b]] = maze[px[b] + c][py[b] + d] ******= maze[px[b] - c][py[b] - d] = b + 1; ****} **} **snr (maze[2][1], UNSEEN); **/* now make an exit */ **maze[1][2 * (rand () % ysize) + 1] = UNSEEN; **x =**2 * xsize; y =**2 * (rand () % ysize) + 1; face = 2; } int look (int f, int s) { **int c, d, r; **c = x + X(face) * f + X(face - 1) * s; **d = y + Y(face) * f + Y(face - 1) * s; **r = maze[c][d]; if (r == UNSEEN) maze[c][d] = SEEN; **return r; } void draw (int col, char *s) { **while (hpos < col) {putchar (' '); hpos++;} **printf ("%s", s); hpos += strlen (s); } void draw3d(void) { **int line, side, depth, p, q, i; ** **putchar ('\n'); **for (line = -11; line <= 11; ++line) { ****for(side = 1, depth = 0; side + 3; side-=2) { ******for (; depth != 2 + 3 * side; depth += side) { ********if(look (depth, 0) < UNSEEN) { **********p = scale[depth]; **********if (abs(line) < p && look(depth, 0) == WALL || abs (line) > p) break; **********for (i = -p; i < p; ++i) draw (MID + i * 2, "--"); **********draw (0, "-"); break; ********} ********if (depth == 5) continue; ********p = scale[depth + 1]; q = scale[depth]; ********if (abs (line) > q) continue; ********if (abs (line) < p) draw (MID - side * (2 * p + 1), "|"); ********else if (look (depth, side)) { **********if (abs (line) <= p) ************for(i = (side == 1 ? -q : p); i != (side == 1 ? -p : q); **************(abs (line)), ++i) **************draw (MID + 2 * i + (side == -1), "--"); ********} else if (abs(line) == p) **********draw (MID - side * (2 * p + 1), "|"); ********else draw (MID - (abs (line) * side * 2), **********(side == 1) ^ (line > 0) ? "\\" : "/"); ******} ******depth -= side; ****} ****putchar ('\n'); hpos=0; **} **if (maze[x][y] != EXIT) maze[x][y] = TRAVL; } int move (void) { **char in; **printf ("\n%c (F)orward, (L)eft or (R)ight? ", "WSEN"[face]); **do in = getche (); while (!isalnum (in)); in = tolower (in); **if (in == 'm') drawmap (); **else { ****if ((in == 'w' || in == 'f') && look (1, 0) != WALL) ******{x += X(face); y += Y(face);} ****if ((in == 's' || in == 'b') && look (-1, 0) != WALL) ******{x -= X(face); y -= Y(face);} ****face += (in == 'd' || in == 'r') + 3 * (in == 'a' || in == 'l'); ****if (in == 'z'&& look (1, 0) != WALL) do {x += X(face); y += Y(face); draw3d ();} ******while (look (1, 0) > WALL && look (0, 1) == WALL && look (0, -1) == WALL); ****draw3d (); face %= 4; **} **return (in != 'q'); } void setsize (void) { **char in; ** **printf ("(E)asy, (M)edium or (H)ard? "); **do { ****do in = getche (); while (!isalnum (in)); in = tolower (in); ****switch (in) { ******case 'e' : xsize = ysize = 5; break; ******case 'm' : xsize = 15; ysize = 11; break; ******case 'h' : xsize = XMAX; ysize = YMAX; break; ******default : printf ("\nInvalad Option. Please choose E, M, or H? "); ********xsize = ysize = 0; ****} **} while (!xsize); } int main (void) { **clock_t st, et; **double secs; ** **srand (time (NULL)); **setsize (); **generate (); **draw3d (); **st = clock (); **while (move () && look (0,0) != EXIT); **if (look (0, 0) == EXIT) { ****et = clock (); ****secs = (double)(et - st) / CLOCKS_PER_SEC; ****snr (UNSEEN, SEEN); ****drawmap (); ****printf ("\nYou escaped the Labryinth in %2.3f seconds!\n", secs); **} **exit (0); } The constants WALL, UNSEEN, SEEN, TRAVL, and EXIT are for the map. When the maze is generated you have WALLs and UNSEEN everywhere and EXIT at the end. As you see an area UNSEEN becomes SEEN and as you go there the spot you stand on becomes TRAVL. That way at the end you can see what path you took through the maze. The maze generating algorithm doesn't make paths through the maze or anything. It just makes sure you can get anywhere from anywhere else one and only one way. It connectes two spaces with a numbered path. If two paths are connected the higher number over rides the other path so that if it wanto to join two areas it only needs to be sure they aren't of the same path, meaining a loop would be generated. A hole is punched in the left side for the exit. I had considered having a square maze, dropping the player in the exact middle, and punching one hole in any of the outside walls, meaning you could wander the wrong direction for a long time before getting out. But I decided against that for a straight east to west progression to make it less diabolical. Besides, a square map of more than 11x11 would not show well on the map printout. This game is so cool I absolutely recomend downloading DevCPP and playing this one. It's a hoot. I wanted to include the executable here, but the boards don't allow it. But you have the code, so go on with you. So there is 3DMaze. What's next?
|
||
![]() ![]() |
|
![]() |
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Happy Birthday Guesst | Japo | Birthdays & Celebrations | 8 | 06-07-2007 09:50 AM |
Happy Birthday, Guesst | Shrek | Blah, blah, blah... | 10 | 08-07-2006 09:31 AM |
|
|
||
  |