#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/times.h>
#include <math.h>

#define USE_LOGO	alien
#define MAXINT		2000000000

char	*flogo[] =
{
// 1234567890123456  1234567890123456  1234567890123456  1234567890123456  1234567890123456
".......+########+...++###+.................+####+.........+########+...........+########+...",
"......####++++####..+#####................####+###.......+####++#####+........####++++####..",
".....###+......++...+#####...............###+...+##......####+....+###+......###+......++...",
"....####+...........+#####..............####.....###....+####+.....+###.....####+...........",
"...+####............+#####.............+###+.....+##+...+####+......###....+####............",
"...#####+...........+#####.............####+.....+###...+####+.....+##+....#####+...........",
"..+######++++.......+#####............+#####+++++####+..+#####+++++#+.....+######++++.......",
"..###########.......+#####............################..#############+....###########.......",
"..#######+..........+#####............#####+.....+####..######+..+#####+..#######+..........",
"..+#####+...........+#####............+####+.....+###+..+#####+...+#####..+#####+...........",
"..+#####+...........+#####............+####+.....+###+..+#####+...+#####..+#####+...........",
"..+#####+...........+#####+...........+####+.....+###+..+#####+...+#####..+#####+...........",
"..######+...........#######+..+####+..#####+.....+####..######+...+#####..#######+..+####+..",
"..######+...........################..#####+.....+####..######+...+#####..################..",
"...+++++.............++++++++++++++....++++.......+++....+++++.....++++....++++++++++++++...",
NULL
};

char	*alien[] =
{
"                                                                 +                                                              ",
"                                                                ++                                                              ",
"                                                               +##+                                                             ",
"                                                              +####+                                                            ",
"                                                              +####+                                                            ",
"                                                             +######+                                                           ",
"                                                             +######+                                                           ",
"                                                             ########                                                           ",
"                                                            +########+                                                          ",
"                                                            +########+                                                          ",
"                                                            +########+                                                          ",
"                                                            ##########                                                          ",
"               +##############                              ##########                                                          ",
"             +################                              ##########                                                          ",
"           +######+   ########           +##                ##########         +############      +#########+         #######+  ",
"          +######+    ########          +###                ##########        +#############       +#########+        ######+   ",
"         ######+      ########         +####                ##########       +#####+                ###########+      ######    ",
"        ######+       ########        +#####                ##########      +#####+                 ############+     ######    ",
"       +#####+        ########       +######                ##########     +######                  ######## +###+    ######    ",
"      +######         ########      +#######                ##########    +#######                  ########  +###+   ######    ",
"     +######+         ########      ########                ##########    ########                  ########   +###+  ######    ",
"     +######          ########      ########                ##########    ########                  ########    +###+ ######    ",
"    +#######          ########      ########                ##########    ########                  ########     +##########    ",
"    +#######          ########      ########                ##########    ########                  ########      +#########    ",
"    ########  +###############      ########                ##########    ##############            ########       +########    ",
"    ######## +################      ########                ##########    ##############            ########        +#######    ",
"    ########          ########      ########                ##########    ########                  ########         +######    ",
"    ########          ########      ########                ##########    ########                  ########         +######    ",
"    ########          ########      ########                ##########    ########                  ########          ######    ",
"    ########          ########      ########                ##########    ########                  ########          ######    ",
"    ########          ########      ########     +######+   ##########    ########     +######+     ########          ######    ",
"    ########          ########      ########    +#######+   ##########    ########    +#######+     ########          ######    ",
"  +##########+      +##########+  +######################+  ##########  +######################+  +##########+       +######+   ",
"  ############      ############  ########################  ##########  ########################  ############      +########+  ",
"                                                            ##########                                                          ",
"                                                            +########+                                                          ",
"                                                            +########+                                                          ",
"                                                            +########+                                                          ",
"                                                             ########                                                           ",
"                                                             +######+                                                           ",
"                                                             +######+                                                           ",
"                                                              +####+                                                            ",
"                                                              +####+                                                            ",
"                                                               +##+                                                             ",
"                                                                ++                                                              ",
"                                                                 +                                                              ",
NULL
};

char	*elogo[] =
{
  "    +#######+                                                                              ",
  "  +####  +###   #######++         +#######+   +#########+        +#######+     +#    ##+   ",
  "  ####          ##########+     +####  +###   #####  +####+    +####  +###    ###    ###+  ",
  " +####          ##### +####+    ####          #####    ####+   ####          ####    ####  ",
  " #####+####     #####   ####   +####          +####+  +###+   +####         +####    ####  ",
  " ########+      #####   +###+  #####+####     ++########      #####   +#### #####+   ####  ",
  " #####+         #####   +####  ########+      ##### +####     #####  ######  +###########  ",
  " #####          #####    ####  #####+         #####   ####    #####    +###        +#####  ",
  " +####   +####  #####    ####  +####   +####  #####    ####   +####    ####         ####+  ",
  "  ############  #####    ###+   ############  ####+    ####+   ############        +####   ",
  "   ++#########  #####    ###     ++#########  ####     #####    ++####+####        +###    ",
  "                         ##                   +##                       ###         ##     ",
  "                         +                     +                         #+         +      ",
//  #############  #############  #############  +#############  ############# #############  .
/*
,-----------------------------------------------------------------.
|   ,-----; ,------,     ,-----; ,-------,    ,----,     ,  ,-.   |
|  /  ,---' |   ,.  \   /  ,---' |   ,--, \  /  ,-. \   /|  |  \  |
| |   |___  |   | \  \ |   |___  |   |__|  ;|   | `~´  / |  |   | |
| |   ,--'  |   |  |  ||   ,--'  |   |--; < |   | ,--,/   `-'   | |
| |   |__,-,|   |  |  ||   |__,-,|   |  |  ||   | \  |\___.     | |
| |        ||   |  |  ||        ||   |  |  ||   `~'  |     \    | |
| |        ||   |  | / |        ||   |  | / |        |      |   | |
| `~~~~~`\/ `---'  `/  `~~~~~`\/ `---'  `/  `/~~~~~~'       |,--' |
|          ,---,    ,---,  ,-----;   ,----.    ,-.  ,--.          |
|          |    \  /    | /  ,---'  /  ,--'   /  |  |  |          |
|          |     \/     ||   |___  |   |     |   |__|  |          |
|          |   |\  /|   ||   ,--'  |   |     |   ,--.  |          |
|          |   | \/ |   ||   |__,-,|   |   /||   |  |  |          |
|          |   |    |   ||        ||   `--' ||   |  |  |          |
|          |   |    |   ||        ||        ||   |  | /           |
|          `---'    `---'`~~~~~`\/ `\___/~~~'`---'  `/            |
`-----------------------------------------------------------------'
*/
NULL
};

/*
 * Small = 123456
 * Big = 3456
 */
#define RANDSEED		3456

#define SCALE			10

#define BOXSIZE			4
#define BOFF			3 /* (10 - BOXSIZE) / 2 */

//#define BOXSIZE			2
//#define BOFF			4

#define BOFF2			4
#define BSZ2			BOFF2+2

#define TEXTURE_001		1

char	*texdef[] =
{
	"TEXDEFAULT",
	"TEX001",
	"TEX002",
	NULL
};

#define RANDOM(min,max)		(min + ((max - min) * (rand() / (RAND_MAX + 1.0))))

#define CENTER	0x0001
#define UP	0x0002
#define DOWN	0x0004
#define FWD	0x0008
#define BACK	0x0010
#define RIGHT	0x0020
#define LEFT	0x0040
/**/
#define dSTATIC	0x0080
/**/
#define dNONE	0x00FF
/**/
#define dCENTER	0x0100
#define dUP	0x0200
#define dDOWN	0x0400
#define dFWD	0x0800
#define dBACK	0x1000
#define dRIGHT	0x2000
#define dLEFT	0x4000

short	*grid;
short	*attr;

#define	pos(x,y,z)	grid[((z)*maxx*maxy)+((y)*maxx)+(x)]
#define	G(x,y,z)	grid[((z)*maxx*maxy)+((y)*maxx)+(x)]
#define	pat(x,y,z)	attr[((z)*maxx*maxy)+((y)*maxx)+(x)]

short	*start;

char	*argp[50];

int	p_guess;

int	maxx,maxy,maxz;

int	rawmesh,hollow,plus,framework,norend,logo,innerlight;
int	xtra,debug;
int	guess_overflow;
double	plasmamutator;

int	pcdone;
int	pcmax;
int	pccount;

int emptycount(void)
{
	int	x,y,z;
	int	ct;

	ct = 0;
	for(x=0;x<maxx;x++)
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		if (pos(x,y,z) == 0)
			ct++;
	}
	return(ct);
}

short *randempty(void)
{
	int	x,y,z;
	int	rn,ct;

	ct = emptycount();
	rn = RANDOM(0,ct);
	for(x=0;x<maxx;x++)
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		if (pos(x,y,z) == 0)
		{
			rn--;
			if (!rn)
				return(&pos(x,y,z));
		}
	}
	return(NULL);
}

int poss_count(void)
{
	int	x,y,z;
	int	n;
	int	f;

	n = 0;
	for(x=0;x<maxx;x++)
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		f = pos(x,y,z);
		if ((f & CENTER) && ((f & dSTATIC) == 0))
		{
			if ((x+1 < maxx) && ((f & RIGHT) == 0) && (pos(x+1,y,z) == 0))
				n++;
			if ((x-1 >= 0) && ((f & LEFT) == 0) && (pos(x-1,y,z) == 0))
				n++;
			if ((y+1 < maxy) && ((f & UP) == 0) && (pos(x,y+1,z) == 0))
				n++;
			if ((y-1 >= 0) && ((f & DOWN) == 0) && (pos(x,y-1,z) == 0))
				n++;
			if ((z+1 < maxz) && ((f & FWD) == 0) && (pos(x,y,z+1) == 0))
				n++;
			if ((z-1 >= 0) && ((f & BACK) == 0) && (pos(x,y,z-1) == 0))
				n++;
		}
	}
	return(n);
}

#define bposs(x,y,z)	((pos(x,y,z) & (CENTER|dSTATIC)) == 0)
#define bnostatic(x,y,z)	((pos(x,y,z) & dSTATIC) == 0)

void guess(int x, int y, int z)
{
	char	*de = "";;

	if (x+1 < maxx)
	{
		if (bposs(x+1,y,z))
		{
			if (debug) de = (pos(x+1,y,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch +X %s\n",de);
			p_guess++;
		}
		else
		{
			if (debug) de = (pos(x+1,y,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch +X %s\n",de);
			if (bnostatic(x+1,y,z))
				p_guess--;
		}
	}
	if (x-1 >= 0)
	{
		if (bposs(x-1,y,z))
		{
			if (debug) de = (pos(x-1,y,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch -X %s\n",de);
			p_guess++;
		}
		else
		{
			if (debug) de = (pos(x-1,y,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch -X %s\n",de);
			if (bnostatic(x-1,y,z))
				p_guess--;
		}
	}
	if (y+1 < maxy)
	{
		if (bposs(x,y+1,z))
		{
			if (debug) de = (pos(x,y+1,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch +Y %s\n",de);
			p_guess++;
		}
		else
		{
			if (debug) de = (pos(x,y+1,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch +Y %s\n",de);
			if (bnostatic(x,y+1,z))
				p_guess--;
		}
	}
	if (y-1 >= 0)
	{
		if (bposs(x,y-1,z))
		{
			p_guess++;
			if (debug) de = (pos(x,y-1,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch -Y %s\n",de);
		}
		else
		{
			if (debug) de = (pos(x,y-1,z) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch -Y %s\n",de);
			if (bnostatic(x,y-1,z))
				p_guess--;
		}
	}
	if (z+1 < maxz)
	{
		if (bposs(x,y,z+1))
		{
			if (debug) de = (pos(x,y,z+1) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch +Z %s\n",de);
			p_guess++;
		}
		else
		{
			if (debug) de = (pos(x,y,z+1) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch +Z %s\n",de);
			if (bnostatic(x,y,z+1))
				p_guess--;
		}
	}
	if (z-1 >= 0)
	{
		if (bposs(x,y,z-1))
		{
			if (debug) de = (pos(x,y,z-1) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"+1 branch -Z %s\n",de);
			p_guess++;
		}
		else
		{
			if (debug) de = (pos(x,y,z-1) & dSTATIC) ? "dSTATIC" : "";
			if (debug) fprintf(stderr,"-1 branch -Z %s\n",de);
			if (bnostatic(x,y,z-1))
				p_guess--;
		}
	}
	if (debug) fprintf(stderr,"---\n");
}

int randnode(void)
{
	int	x,y,z;
	int	poss;
	int	rn,gp,sv_poss;

	sv_poss = 0;
retry:
	if (start)
	{
		*start = CENTER;
		start = NULL;
		p_guess = poss_count();
		return(0);
	}
	/*
	 *  Count possible expansions...
	 */
	if (debug)
	{
		sv_poss = poss = poss_count();
		if (poss != p_guess)
		{
			guess_overflow++;
			sv_poss = poss;
		}
	}

	poss = p_guess;

	if (poss == 0)
	{
		if (logo)
		{
			start = randempty();
			if (start)
				goto retry;
		}
		fprintf(stderr,"\nOops: No new nodes possible\n");
		return(1);
	}

	/*
	 *  Choose one at random...
	 */
	rn = RANDOM(0,poss);

	if (debug)
	{
		fprintf(stderr,"%i: Possible branches %i (%i),"
			" RND = %i\n",pccount,p_guess,sv_poss,rn);
	}
	else
	if ((pccount & 0x2f) == 0x2f) fprintf(stderr,"\r%i: Possible branches %i,"
		" RND = %i        ",
		pccount,p_guess,rn);

	poss = 0;
	for(x=0;x<maxx;x++)
	{
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		if (((gp = pos(x,y,z)) & CENTER) && ((gp & dSTATIC) == 0))
		{
			if ((y+1 < maxy) && ((gp & UP) == 0) && (pos(x,y+1,z) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= UP;
					pos(x,y+1,z) |= CENTER|DOWN;
if (debug) fprintf(stderr,"Added UP branch to xyz %i, %i, %i\n",x,y,z);
					guess(x,y+1,z);
					return(0);
				}
				poss++;
			}
			if ((y-1 >= 0) && ((gp & DOWN) == 0) && (pos(x,y-1,z) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= DOWN;
					pos(x,y-1,z) |= CENTER|UP;
if (debug) fprintf(stderr,"Added DOWN branch to xyz %i, %i, %i\n",x,y,z);
					guess(x,y-1,z);
					return(0);
				}
				poss++;
			}
			if ((z+1 < maxz) && ((gp & FWD) == 0) && (pos(x,y,z+1) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= FWD;
					pos(x,y,z+1) |= CENTER|BACK;
if (debug) fprintf(stderr,"Added FWD branch to xyz %i, %i, %i\n",x,y,z);
					guess(x,y,z+1);
					return(0);
				}
				poss++;
			}
			if ((z-1 >= 0) && ((gp & BACK) == 0) && (pos(x,y,z-1) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= BACK;
					pos(x,y,z-1) |= CENTER|FWD;
if (debug) fprintf(stderr,"Added BACK branch to xyz %i, %i, %i\n",x,y,z);
					guess(x,y,z-1);
					return(0);
				}
				poss++;
			}
			if ((x+1 < maxx) && ((gp & RIGHT) == 0) && (pos(x+1,y,z) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= RIGHT;
					pos(x+1,y,z) |= CENTER|LEFT;
if (debug) fprintf(stderr,"Added RIGHT branch to xyz %i, %i, %i\n",x,y,z);
					guess(x+1,y,z);
					return(0);
				}
				poss++;
			}
			if ((x-1 >= 0) && ((gp & LEFT) == 0) && (pos(x-1,y,z) == 0))
			{
				if (rn == poss)
				{
					pos(x,y,z) |= LEFT;
					pos(x-1,y,z) |= CENTER|RIGHT;
if (debug) fprintf(stderr,"Added LEFT branch to xyz %i, %i, %i\n",x,y,z);
					guess(x-1,y,z);
					return(0);
				}
				poss++;
			}
		}
	}
	}
	return(1);
}

#define P1	x1,y1,z1
#define P2	x2,y1,z1
#define P3	x1,y2,z1
#define P4	x2,y2,z1
#define P5	x1,y1,z2
#define P6	x2,y1,z2
#define P7	x1,y2,z2
#define P8	x2,y2,z2

struct
{
	int	maxx,maxy,maxz;
	int	minx,miny,minz;

} comment;

void makebox(FILE *inc, int x1, int y1, int z1, int x2, int y2, int z2, char *texture)
{
	if (rawmesh)
	{
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P1,P5,P2);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P5,P6,P2);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P3,P7,P5);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P3,P5,P1);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P7,P8,P6);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P7,P6,P5);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P7,P8,P4);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P7,P4,P3);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P8,P6,P2);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P8,P2,P4);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P3,P4,P2);
		fprintf(inc," %i %i %i %i %i %i %i %i %i\r\n",P3,P2,P1);
		return;
	}

	if (comment.maxx < x1) comment.maxx = x1;
	if (comment.maxx < x2) comment.maxx = x2;
	if (comment.maxy < y1) comment.maxy = y1;
	if (comment.maxy < y2) comment.maxy = y2;
	if (comment.maxz < z1) comment.maxz = z1;
	if (comment.maxz < z2) comment.maxz = z2;

	if (comment.minx > x1) comment.minx = x1;
	if (comment.minx > x2) comment.minx = x2;
	if (comment.miny > y1) comment.miny = y1;
	if (comment.miny > y2) comment.miny = y2;
	if (comment.minz > z1) comment.minz = z1;
	if (comment.minz > z2) comment.minz = z2;

	fprintf(inc,"box { < %i, %i, %i > < %i, %i, %i > }\r\n",
		x1,y1,z1,x2,y2,z2);
}
void makeboxtx(FILE *inc, int x1, int y1, int z1, int x2, int y2, int z2, char *texture)
{
	fprintf(inc,"box { < %i, %i, %i > < %i, %i, %i > %s }\r\n",
		x1,y1,z1,x2,y2,z2,texture);
}

void render(void)
{
	FILE	*inc;
	int	x,y,z;
	int	o,l,cd,len,n,ox,poss;
	struct tms t;

	comment.maxx = -MAXINT;
	comment.maxy = -MAXINT;
	comment.maxz = -MAXINT;
	comment.minx = MAXINT;
	comment.miny = MAXINT;
	comment.minz = MAXINT;

	inc = fopen("object.inc","w+");
	o = 0;
	ox = 0;
	poss = 0;
	for(x=0;x<maxx;x++)
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		cd = (pos(x,y,z) & dCENTER) ? BOXSIZE : 0;
		if ((pos(x,y,z) & (UP|dUP)) == UP)
		{
			l = 0;
			while(1)
			{
				if ((pos(x,y+l,z) & (UP|dUP)) != UP)
					break;
				pos(x,y+l,z) |= (dUP|dCENTER);
				pos(x,y+l+1,z) |= dDOWN;
				l++;
			}
			len = l * (BOXSIZE+BOFF+BOFF);
			if (pos(x,y+l,z) == (CENTER|DOWN|dDOWN))
			{
				pos(x,y+l,z) |= dCENTER;
				len += BOXSIZE;
			}
			makebox(inc,
				x*SCALE+BOFF,y*SCALE+BOFF+cd,z*SCALE+BOFF,
				x*SCALE+BOFF+BOXSIZE,y*SCALE+BOFF+len,z*SCALE+BOFF+BOXSIZE,
				texdef[pat(x,y,z)]);
			o++;
		}
		cd = (pos(x,y,z) & dCENTER) ? BOXSIZE : 0;
		if ((pos(x,y,z) & (FWD|dFWD)) == FWD)
		{
			l = 0;
			while(1)
			{
				if ((pos(x,y,z+l) & (FWD|dFWD)) != FWD)
					break;
				pos(x,y,z+l) |= (dFWD|dCENTER);
				pos(x,y,z+l+1) |= dBACK;
				l++;
			}
			len = l * (BOXSIZE+BOFF+BOFF);
			if (pos(x,y,z+l) == (CENTER|BACK|dBACK))
			{
				pos(x,y,z+l) |= dCENTER;
				len += BOXSIZE;
			}
			makebox(inc,
				x*SCALE+BOFF,y*SCALE+BOFF,z*SCALE+BOFF+cd,
				x*SCALE+BOFF+BOXSIZE,y*SCALE+BOFF+BOXSIZE,z*SCALE+BOFF+len,
				texdef[pat(x,y,z)]);
			o++;
		}
		cd = (pos(x,y,z) & dCENTER) ? BOXSIZE : 0;
		if ((pos(x,y,z) & (RIGHT|dRIGHT)) == RIGHT)
		{
			l = 0;
			while(1)
			{
				if ((pos(x+l,y,z) & (RIGHT|dRIGHT)) != RIGHT)
					break;
				pos(x+l,y,z) |= (dRIGHT|dCENTER);
				pos(x+l+1,y,z) |= dLEFT;
				l++;
			}
			len = l * (BOXSIZE+BOFF+BOFF);
			if (pos(x+l,y,z) == (CENTER|BACK|dBACK))
			{
				pos(x+l,y,z) |= dCENTER;
				len += BOXSIZE;
			}
			makebox(inc,
				x*SCALE+BOFF+cd,y*SCALE+BOFF,z*SCALE+BOFF,
				x*SCALE+BOFF+len,y*SCALE+BOFF+BOXSIZE,z*SCALE+BOFF+BOXSIZE,
				texdef[pat(x,y,z)]);
			o++;
		}
		if ((pos(x,y,z) & (CENTER|dCENTER)) == CENTER)
		{
			makebox(inc,
				x*SCALE+BOFF,y*SCALE+BOFF,z*SCALE+BOFF,
				x*SCALE+BOFF+BOXSIZE,y*SCALE+BOFF+BOXSIZE,z*SCALE+BOFF+BOXSIZE,
				texdef[pat(x,y,z)]);
			o++;
		}

		if (xtra == 1 && ((pos(x,y,z) & (CENTER|dSTATIC)) == 0))
		{
			n = poss;
			if ((x+1 < maxx) && (pos(x+1,y,z) & CENTER))
				poss++;
			if ((x-1 >= 0) && (pos(x-1,y,z) & CENTER))
				poss++;
			if ((y+1 < maxy) && (pos(x,y+1,z) & CENTER))
				poss++;
			if ((y-1 >= 0) && (pos(x,y-1,z) & CENTER))
				poss++;
			if ((z+1 < maxz) && (pos(x,y,z+1) & CENTER))
				poss++;
			if ((z-1 >= 0) && (pos(x,y,z-1) & CENTER))
				poss++;

			if (n != poss)
			{
				fprintf(stderr,"xtra box at x %i, y %i, z %i\n",x,y,z);
				makebox(inc,
				x*SCALE+BOFF2,y*SCALE+BOFF2,z*SCALE+BOFF2,
				x*SCALE+BSZ2,y*SCALE+BSZ2,z*SCALE+BSZ2,
				"TEX003");
				ox++;
			}
		}
		else
		if (xtra == 1 && ((pos(x,y,z) & (CENTER|dSTATIC)) == dSTATIC))
		{
			fprintf(stderr,"static box at x %i, y %i, z %i\n",x,y,z);
			makebox(inc,
				x*SCALE+BOFF2,y*SCALE+BOFF2,z*SCALE+BOFF2,
				x*SCALE+BSZ2,y*SCALE+BSZ2,z*SCALE+BSZ2,
				"TEX004");
		}
	}

	fprintf(inc,"\r\n");
	fprintf(inc,"// maxx = %i\r\n",comment.maxx);
	fprintf(inc,"// maxy = %i\r\n",comment.maxy);
	fprintf(inc,"// maxz = %i\r\n",comment.maxz);
	fprintf(inc,"// minx = %i\r\n",comment.minx);
	fprintf(inc,"// miny = %i\r\n",comment.miny);
	fprintf(inc,"// minz = %i\r\n",comment.minz);
	fprintf(inc,"\r\n");

	x = (maxx*SCALE)/2;
	y = (maxy*SCALE)/2;
	z = (maxz*SCALE)/2;
	fprintf(inc,"translate < %i, %i, %i >\r\n",-x,-y,-z);
	fprintf(stderr,"translate < %i, %i, %i >\r\n",-x,-y,-z);
	fclose(inc);

	fprintf(stderr,"Objects: %i\nXtra: %i/poss %i, guess_overflow %i\n\n",
		o,ox,poss,guess_overflow);

	times(&t);

	x = t.tms_utime;
	y = t.tms_stime;
	fprintf(stderr,"utime %i\nstime %i\n\n",x,y);

	/*
	 *  Reset drawn attributes
	 */
	for(x=0;x<maxx;x++)
	for(y=0;y<maxy;y++)
	for(z=0;z<maxz;z++)
	{
		pos(x,y,z) &= dNONE;
	}
	/*
	 *  Render the fuqr
	 */
/*
	if (!norend)
	{
		if (fork() == 0)
		{
			execvp("povray",argp);
			exit(1);
		}
		wait(NULL);
	}
*/
}

void plasmapixel2(int x, int y, int z, int col, int dist)
{
	double	fcol;
	double	mut;

	fcol = (1.0*col)/2;

	mut = plasmamutator * (dist/(0.333*(maxx+maxy+maxz)));

	fcol = RANDOM(0,round(mut)) + fcol - (mut/2);
	pos(x,y,z) = round(fcol);
}

void plasmapixel4(int x, int y, int z, int col, int dist)
{
	double	fcol;
	double	mut;

	fcol = (1.0*col)/4;

	mut = (1.0*dist)/2;

	mut = plasmamutator * (mut/(0.333*(maxx+maxy+maxz)));

	fcol = RANDOM(0,round(mut)) + fcol - (mut/2);
	pos(x,y,z) = round(fcol);
}

int sublevel;

void plasmasub(int x1, int y1, int z1, int x2, int y2, int z2)
{
	int	x,y,z;
	double	fcol;
	double	mut;

	x = round((x1+x2)/2);
	y = round((y1+y2)/2);
	z = round((z1+z2)/2);

	if (x == x1 && y == y1 && z == z1)
		return;
	if (pos(x,y,z) != 0)
		return;

	sublevel++;

	if (debug) fprintf(stderr,"Entering sublevel %i\n",sublevel);


	// box front

	if (pos(x1,y,z1) == 0) plasmapixel2(x1,y,z1,pos(x1,y1,z1)+pos(x1,y2,z1),(y2-y1));
	if (pos(x2,y,z1) == 0) plasmapixel2(x2,y,z1,pos(x2,y1,z1)+pos(x2,y2,z1),(y2-y1));
	if (pos(x,y1,z1) == 0) plasmapixel2(x,y1,z1,pos(x1,y1,z1)+pos(x2,y1,z1),(x2-x1));
	if (pos(x,y2,z1) == 0) plasmapixel2(x,y2,z1,pos(x1,y2,z1)+pos(x2,y2,z1),(x2-x1));

	if (pos(x,y,z1) == 0) plasmapixel4(x,y,z1,pos(x1,y,z1)+pos(x2,y,z1)
		+pos(x,y1,z1)+pos(x,y2,z1),(x2-x1)+(y2-y1));

	// box back

	if (pos(x1,y,z2) == 0) plasmapixel2(x1,y,z2,pos(x1,y1,z2)+pos(x1,y2,z2),(y2-y1));
	if (pos(x2,y,z2) == 0) plasmapixel2(x2,y,z2,pos(x2,y1,z2)+pos(x2,y2,z2),(y2-y1));
	if (pos(x,y1,z2) == 0) plasmapixel2(x,y1,z2,pos(x1,y1,z2)+pos(x2,y1,z2),(x2-x1));
	if (pos(x,y2,z2) == 0) plasmapixel2(x,y2,z2,pos(x1,y2,z2)+pos(x2,y2,z2),(x2-x1));

	if (pos(x,y,z2) == 0) plasmapixel4(x,y,z2,pos(x1,y,z2)+pos(x2,y,z2)
		+pos(x,y1,z2)+pos(x,y2,z2),(x2-x1)+(y2-y1));

	if (pos(x1,y1,z) == 0) plasmapixel2(x1,y1,z,pos(x1,y1,z1)+pos(x1,y1,z2),(z2-z1));
	if (pos(x1,y2,z) == 0) plasmapixel2(x1,y2,z,pos(x1,y2,z1)+pos(x1,y2,z2),(z2-z1));
	if (pos(x2,y1,z) == 0) plasmapixel2(x2,y1,z,pos(x2,y1,z1)+pos(x2,y1,z2),(z2-z1));
	if (pos(x2,y2,z) == 0) plasmapixel2(x2,y2,z,pos(x2,y2,z1)+pos(x2,y2,z2),(z2-z1));

	if (pos(x1,y,z) == 0) plasmapixel4(x1,y,z,pos(x1,y,z1)+pos(x1,y1,z)
		+pos(x1,y,z2)+pos(x1,y2,z),(y2-y1)+(z2-z1));

	if (pos(x2,y,z) == 0) plasmapixel4(x2,y,z,pos(x2,y,z1)+pos(x2,y1,z)
		+pos(x2,y,z2)+pos(x2,y2,z),(y2-y1)+(z2-z1));

	if (pos(x,y1,z) == 0) plasmapixel4(x,y1,z,pos(x,y1,z1)+pos(x,y1,z2)
		+pos(x1,y1,z)+pos(x2,y1,z),(x2-x1)+(z2-z1));

	if (pos(x,y2,z) == 0) plasmapixel4(x,y2,z,pos(x,y2,z1)+pos(x,y2,z2)
		+pos(x1,y2,z)+pos(x2,y2,z),(x2-x1)+(z2-z1));

	/* this last one needs to be an average of 6 pixels */

	fcol = (1.0 * pos(x1,y,z)+pos(x2,y,z)+pos(x,y1,z)
		+pos(x,y2,z)+pos(x,y,z1)+pos(x,y,z2))/6;

	mut = (1.0 * ((x2-x1) + (y2-y1) + (z2-z1)))/3;

	mut = plasmamutator * (mut/(0.333*(maxx+maxy+maxz)));

	fcol = RANDOM(0,round(mut)) + fcol - (mut/2);
	if (pos(x,y,z) == 0)
		pos(x,y,z) = round(fcol);

	plasmasub(x1,y1,z1,x,y,z);
	plasmasub(x,y1,z1,x2,y,z);
	plasmasub(x1,y,z1,x,y2,z);
	plasmasub(x,y,z1,x2,y2,z);

	if (debug) fprintf(stderr,"Halfway..\n");

	plasmasub(x1,y1,z,x,y,z2);
	plasmasub(x,y1,z,x2,y,z2);
	plasmasub(x1,y,z,x,y2,z2);
	plasmasub(x,y,z,x2,y2,z2);

	if (debug) fprintf(stderr,"Exiting sublevel %i ( %i, %i, %i -- %i, %i, %i )\n",
		sublevel,x1,y1,z1,x2,y2,z2);

	sublevel--;
}

typedef struct PosDef
{
        int	x,y,z,used;

} PosDef;

int main(int argc, char **argv)
{
	FILE	*inc;
	char	*pt;
	int	sphere,plasma,slice;
	int	i,cut,cutpc,cutframe;
	int	x,y,z,max,o;
	double	cutd;

	srand(RANDSEED);

	cutd = 0;
	cut = 0;
	logo = norend = framework = plus = hollow = rawmesh = 0;
	debug = xtra = guess_overflow = sphere = plasma = slice = 0;
	p_guess = cutframe = cutpc = -1;

	maxx = maxy = maxz = 10;

	argp[0] = "povray";
	i = 1;
	argv++;
	while(*argv)
	{
		if (**argv == '%')
		{
			pt = *argv;
			pt++;
			if (!strcmp(pt,"sphere"))
				sphere = 1;
			else
			if (!strcmp(pt,"plasma"))
				plasma = 1;

			switch(*pt)
			{
			case 'x':
				pt++;
				maxx = atoi(pt);
				break;
			case 'y':
				pt++;
				maxy = atoi(pt);
				break;
			case 'z':
				pt++;
				maxz = atoi(pt);
				break;
			case 'p':
				pt++;
				cutpc = atoi(pt);
				break;
			case 'f':
				pt++;
				cutframe = atoi(pt);
				break;
			case 'C':
				pt++;
				if (strchr(pt,'.'))
				{
					cutd = atof(pt);
				}
				else
				{
					cut = atoi(pt);
				}
				break;
			case 'M':
				rawmesh = 1;
				break;
			case 'H':
				hollow = 1;
				break;
			case 'P':
				plus = 1;
				break;
			case 'F':
				framework = 1;
				break;
			case 'm':
				pt++;
				plasmamutator = atof(pt);
				break;
			case 'R':
				pt++;
				x = atoi(pt);
				srand(x);
				break;
			case 'Q':
				norend++;
				break;
			case 'S':
				slice++;
				break;
			case 'L':
				logo++;
				break;
			case 'I':
				pt++;
				innerlight = atoi(pt);
				break;
			case 'D':
				debug = 1;
				break;
			case 'X':
				xtra = 1;
				break;
			}
			argv++;
			continue;
		}
		argp[i++] = *argv;
		argv++;
	}
	argp[i] = NULL;

	/*
	 *  Prepare the initial grid
	 */
	grid = calloc(1,maxx*maxy*maxz*2);
	attr = calloc(1,maxx*maxy*maxz*2);

	pcdone = 0;
	pccount = 0;

	start = NULL;

	if (plasmamutator <= 0)
		plasmamutator = 255;

	if (hollow && cut)
	{
		fprintf(stderr,"Hollow, saving = %i\n",cut);
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			if (x>=cut && x<maxx-cut && y>=cut && y<maxy-cut)
				pos(x,y,z) = dSTATIC;
			else
			if (z>=cut && z<maxz-cut && x>=cut && x<maxx-cut)
				pos(x,y,z) = dSTATIC;
			else
			if (y>=cut && y<maxy-cut && z>=cut && z<maxz-cut)
				pos(x,y,z) = dSTATIC;
		}
	}

	if (plus && cut)
	{
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			i = 0;
			if (x>=cut && x<maxx-cut && y>=cut && y<maxy-cut)
				i++;
			else
			if (z>=cut && z<maxz-cut && x>=cut && x<maxx-cut)
				i++;
			else
			if (y>=cut && y<maxy-cut && z>=cut && z<maxz-cut)
				i++;

			if (i == 0)
				pos(x,y,z) = dSTATIC;
		}
		start = &pos(maxx >> 1,maxy >> 1,maxz >> 1);
	}

	if (sphere)
	{
		double	midx,midy,midz;
		double	dist,xdist,ydist,zdist;
		double	maxdist;

		maxdist = 0;

		midx = (maxx/2.0);
		midy = (maxy/2.0);
		midz = (maxz/2.0);

		if (cut == 0 && cutd == 0)
			cutd = midx;

		fprintf(stderr,"Sphere: Center distance to side = %f\n",midx);
		fprintf(stderr,"Sphere: cutdist = %f\n",cutd);

		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			xdist = (midx-x) * (midx-x);
			ydist = (midy-y) * (midy-y);
			zdist = (midz-z) * (midz-z);
			dist = sqrt(xdist+ydist);
			dist = dist * dist;
			dist = sqrt(dist+zdist);
			if (dist > maxdist)
				maxdist = dist;
			if (debug) fprintf(stderr,"dist %8.8f\n",dist);
			if (dist > cutd)
				pos(x,y,z) |= dSTATIC;
		}
		fprintf(stderr,"Sphere: maxdist = %f\n",maxdist);
		start = randempty();
	}

	if (plasma)
	{
		char	tx[100];
		double	col;
		FILE	*inc;

		fprintf(stderr,"Building Plasma...\r\n");
		fprintf(stderr,"Plasma: mutator = %f\n",plasmamutator);

		pos(0,0,0) = RANDOM(1,255);
		pos(maxx-1,0,0) = RANDOM(1,255);
		pos(0,maxy-1,0) = RANDOM(1,255);
		pos(maxx-1,maxy-1,0) = RANDOM(1,255);
		pos(0,0,maxz-1) = RANDOM(1,255);
		pos(maxx-1,0,maxz-1) = RANDOM(1,255);
		pos(0,maxy-1,maxz-1) = RANDOM(1,255);
		pos(maxx-1,maxy-1,maxz-1) = RANDOM(1,255);

		sublevel = 0;
		plasmasub(0,0,0,maxx-1,maxy-1,maxz-1);

		fprintf(stderr,"Plasma: Writing file \"plasma.inc\"...\n");
		inc = fopen("plasma.inc","w+");

		if (slice)
		{
		
			fprintf(stderr,"Writing plasma slices...\n");
			for (i=0;i<4;i++)
			{
				if (i == 0)
					z = 0;
				if (i == 1)
					z = round(0.3333*maxz);
				if (i == 2)
					z = round(0.6666*maxz);
				if (i == 3)
					z = maxz-1;
	
				for(x=0;x<maxx;x++)
				for(y=0;y<maxy;y++)
				{

					if (pos(x,y,z) > 255)
						col = 1;
					else
						col = pos(x,y,z) / 255.0;
					sprintf(tx,"texture { pigment { color rgb < %f, %f, %f > }}",
						col,col,col);
					makeboxtx(inc,x*SCALE,y*SCALE,z*SCALE,
						x*SCALE+SCALE,y*SCALE+SCALE,z*SCALE+SCALE,
						tx);
				}
			}
		}
		else
		{
			o = 0;
			fprintf(stderr,"Writing solid block plasma...\n");
			for(x=0;x<maxx;x++)
			for(y=0;y<maxy;y++)
			for(z=0;z<maxz;z++)
			{
				if (x == 0 || y == 0 || z == 0 || x == maxx-1 || y == maxy-1 || z == maxz-1)
				{
				if (pos(x,y,z) > 255)
					col = 1;
				else
					col = pos(x,y,z) / 255.0;
				sprintf(tx,"texture { pigment { color rgb < %f, %f, %f > }}",
					col,col,col);
				makeboxtx(inc,x*SCALE,y*SCALE,z*SCALE,
					x*SCALE+SCALE,y*SCALE+SCALE,z*SCALE+SCALE,
					tx);
					o++;
				}
			}
			fprintf(stderr,"Plasma: %i objects written (out of %i)\n",
				o,(maxx*maxy*maxz));
		}
		x = (maxx*SCALE)/2;
		y = (maxy*SCALE)/2;
		z = (maxz*SCALE)/2;
		fprintf(inc,"translate < %i, %i, %i >\r\n",-x,-y,-z);
		fprintf(stderr,"translate < %i, %i, %i >\r\n",-x,-y,-z);
		fclose(inc);
		return(0);
	}

	if (framework)
	{
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			if (x == 0 || x == maxx-1)
			{
				pos(x,y,z) = dSTATIC;
				if (y == 0 || y == maxy-1)
				{
					pos(x,y,z) |= CENTER;
					pat(x,y,z) = TEXTURE_001;
					if (z > 0)
						pos(x,y,z) |= BACK;
					if (z < maxz-1)
						pos(x,y,z) |= FWD;
				}
				if (z == 0 || z == maxz-1)
				{
					pos(x,y,z) |= CENTER;
					pat(x,y,z) = TEXTURE_001;
					if (y > 0)
						pos(x,y,z) |= DOWN;
					if (y < maxy-1)
						pos(x,y,z) |= UP;
				}
			}
			if (y == 0 || y == maxy-1)
			{
				pos(x,y,z) |= dSTATIC;
				if (z == 0 || z == maxz-1)
				{
					pos(x,y,z) |= CENTER;
					pat(x,y,z) = TEXTURE_001;
					if (x > 0)
						pos(x,y,z) |= LEFT;
					if (x < maxx-1)
						pos(x,y,z) |= RIGHT;
				}
			}
			if (z == 0 || z == maxz-1)
				pos(x,y,z) |= dSTATIC;
		}
		start = &pos(maxx>>1,maxy>>1,maxz>>1);
	}

	if (logo == 2)
	{
		int	lx,ly,xp,yp,zp;
		char	ch;

		lx = 2 * strlen(USE_LOGO[0]);
		for(ly=0;(USE_LOGO[ly]);)
			ly++;

		ly *= 2;
		if (maxx<lx || maxy<ly || maxz<4)
		{
			fprintf(stderr,"Matrix too small for logo (%ix%ix4 vs. %ix%ix%i)\n",
				lx,ly,maxx,maxy,maxz);
			exit(1);
		}
		xp = (maxx - lx) >> 1;
		yp = (maxy - ly) >> 1;
		zp = (maxz - 4) >> 1;
		fprintf(stderr,"Logo: xoff,yoff,zoff = %i,%i,%i; size = %i,%i,%i\n",xp,yp,zp,lx,ly,4);
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			pos(x,y,z) = dSTATIC;
			if (x >= xp && x < xp+lx && y >= yp && y < yp+ly && z >= zp && z < zp+4)
			{
				ch = USE_LOGO[(((ly-1)-(y-yp))/2)][((x-xp)/2)];
				switch(ch)
				{
				case '+':
					if (z == zp || z == zp+3)
						break;
				case '#':
					pos(x,y,z) = 0;
					break;
				}
			}
		}
		start = randempty();
	}
	else
	if (logo)
	{
		int	lx,ly,xp,yp,zp;
		char	ch;

		lx = strlen(USE_LOGO[0]);
		for(ly=0;(USE_LOGO[ly]);)
			ly++;

		if (maxx<lx || maxy<ly || maxz<4)
		{
			fprintf(stderr,"Matrix too small for logo (%ix%ix4 vs. %ix%ix%i)\n",
				lx,ly,maxx,maxy,maxz);
			exit(1);
		}
		xp = (maxx - lx) >> 1;
		yp = (maxy - ly) >> 1;
		zp = (maxz - 4) >> 1;
		fprintf(stderr,"Logo: xoff,yoff,zoff = %i,%i,%i; size = %i,%i,%i\n",xp,yp,zp,lx,ly,4);
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			pos(x,y,z) = dSTATIC;
			if (x >= xp && x < xp+lx && y >= yp && y < yp+ly && z >= zp && z < zp+4)
			{
				ch = USE_LOGO[(ly-1)-(y-yp)][x-xp];
				switch(ch)
				{
				case '+':
					if (z == zp || z == zp+3)
						break;
				case '#':
					pos(x,y,z) = 0;
					break;
				}
			}
		}
		start = randempty();
	}

	if (!start)
		start = &pos(0,0,0);

	pcmax = emptycount();
	fprintf(stderr,"Nodes to create: %i\n",pcmax);

	if (cutpc >= 0 && pcdone >= cutpc)
	{
		render();
		exit(0);
	}
	if (cutframe >= 0 && pccount >= cutframe)
	{
		render();
		exit(0);
	}

	while(randnode() == 0)
	{
		pccount++;

		if (cutpc >= 0 && pcdone >= cutpc)
			break;
		if (cutframe >= 0 && pccount >= cutframe)
			break;
	}
	fprintf(stderr,"\r\n");

        max = maxx*maxy*maxz;

	if (innerlight)
	{
		int	rn;
                PosDef *possys;

                calloc(1,sizeof(PosDef)*max);

		i = 0;

		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			if (
				(pos( x,   y,   z   ) & CENTER) &&
				(pos( x+1, y,   z   ) & CENTER) &&
				(pos( x,   y+1, z   ) & CENTER) &&
				(pos( x+1, y+1, z   ) & CENTER) &&
				(pos( x,   y,   z+1 ) & CENTER) &&
				(pos( x+1, y,   z+1 ) & CENTER) &&
				(pos( x,   y+1, z+1 ) & CENTER) &&
				(pos( x+1, y+1, z+1 ) & CENTER)
				)
			{
				possys[i].x = x;
				possys[i].y = y;
				possys[i].z = z;
				i++;
			}
		}

		fprintf(stderr,"innerlight possys = %i, number to set = %i\n",i,innerlight);

		inc = fopen("innerlight.inc","w+");
		while(innerlight > 0)
		{
			do
			{
				rn = RANDOM(0,i);
			} while(possys[rn].used != 0);
			possys[rn].used = 1;
			fprintf(inc,"INNERLIGHT(%i,%i,%i)\r\n",
				possys[rn].x*SCALE,possys[rn].y*SCALE,possys[rn].z*SCALE);
			innerlight--;
		}
		fclose(inc);
	}

	render();
	return(0);
}
