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

#define USE_LOGO	alien
#define MAXINT		2000000000
#define PI		3.141592654
#define PTC		0.8

#include "logo.h"

/*
 * 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;
short	*dens;

#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	D(x,y,z)	dens[((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,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 = 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)
		{
			if (dens)
				ct += D(x,y,z);
			else
				ct++;
		}
	}
	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)
		{
			if (dens)
				rn -= D(x,y,z);
			else
				rn--;
			if (rn <= 0)
				return(&pos(x,y,z));
		}
	}
	return(NULL);
}

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

	n = 0;

	if (dens)
	{
		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 += D(x,y,z) + D(x+1,y,z);
				if ((x-1 >= 0) && ((f & LEFT) == 0) && (pos(x-1,y,z) == 0))
					n += D(x,y,z) + D(x-1,y,z);
				if ((y+1 < maxy) && ((f & UP) == 0) && (pos(x,y+1,z) == 0))
					n += D(x,y,z) + D(x,y+1,z);
				if ((y-1 >= 0) && ((f & DOWN) == 0) && (pos(x,y-1,z) == 0))
					n += D(x,y,z) + D(x,y-1,z);
				if ((z+1 < maxz) && ((f & FWD) == 0) && (pos(x,y,z+1) == 0))
					n += D(x,y,z) + D(x,y,z+1);
				if ((z-1 >= 0) && ((f & BACK) == 0) && (pos(x,y,z-1) == 0))
					n += D(x,y,z) + D(x,y,z-1);
			}
		}
	}
	else
	{
		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++;
			}
		}
	}
	if (debug) fprintf(stderr,"poss_count = %i\r\n",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 iterguess(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");
}

#define diffy(a,b) if (debug) iffy(a,b);

void iffy(short *p, char *fmt)
{
	if (*p & dSTATIC)
		fprintf(stderr,fmt,"dSTATIC");
	else
		fprintf(stderr,fmt,"");
}

void densguess(int x, int y, int z, int direction)
{
	p_guess -= D(x,y,z);
	switch(direction)
	{
	case RIGHT:
		x = x+1;
		break;
	case LEFT:
		x = x-1;
		break;
	case UP:
		y = y+1;
		break;
	case DOWN:
		y = y-1;
		break;
	case FWD:
		z = z+1;
		break;
	case BACK:
		z = z-1;
		break;
	}
	p_guess -= D(x,y,z);

	// RIGHT
	if (x+1 < maxx)
	{
		if (bposs(x+1,y,z))
		{
			diffy(&pos(x+1,y,z),"+1 branch +X %s\n");
			p_guess += D(x,y,z) + D(x+1,y,z);
		}
		else
		if (bnostatic(x+1,y,z))
		{
			diffy(&pos(x+1,y,z),"-1 branch +X %s\n");
			p_guess -= D(x,y,z) + D(x+1,y,z);
		}
	}
	// LEFT
	if (x-1 >= 0)
	{
		if (bposs(x-1,y,z))
		{
			diffy(&pos(x-1,y,z),"+1 branch -X %s\n");
			p_guess += D(x,y,z) + D(x-1,y,z);
		}
		else
		if (bnostatic(x-1,y,z))
		{
			diffy(&pos(x-1,y,z),"-1 branch -X %s\n");
			p_guess -= D(x,y,z) + D(x-1,y,z);
		}
	}
	// UP
	if (y+1 < maxy)
	{
		if (bposs(x,y+1,z))
		{
			diffy(&pos(x,y+1,z),"+1 branch +Y %s\n");
			p_guess += D(x,y,z) + D(x,y+1,z);
		}
		else
		if (bnostatic(x,y+1,z))
		{
			diffy(&pos(x,y+1,z),"-1 branch +Y %s\n");
			p_guess += D(x,y,z) + D(x,y+1,z);
		}
	}
	// DOWN
	if (y-1 >= 0)
	{
		if (bposs(x,y-1,z))
		{
			diffy(&pos(x,y-1,z),"+1 branch -Y %s\n");
			p_guess += D(x,y,z) + D(x,y-1,z);
		}
		else
		if (bnostatic(x,y-1,z))
		{
			diffy(&pos(x,y-1,z),"-1 branch -Y %s\n");
			p_guess += D(x,y,z) + D(x,y-1,z);
		}
	}
	// FWD
	if (z+1 < maxz)
	{
		if (bposs(x,y,z+1))
		{
			diffy(&pos(x,y,z+1),"+1 branch +Z %s\n");
			p_guess += D(x,y,z) + D(x,y,z+1);
		}
		else
		if (bnostatic(x,y,z+1))
		{
			diffy(&pos(x,y,z+1),"-1 branch +Z %s\n");
			p_guess += D(x,y,z) + D(x,y,z+1);
		}
	}
	// BACK
	if (z-1 >= 0)
	{
		if (bposs(x,y,z-1))
		{
			diffy(&pos(x,y,z-1),"+1 branch -Z %s\n");
			p_guess += D(x,y,z) + D(x,y,z-1);
		}
		else
		if (bnostatic(x,y,z-1))
		{
			diffy(&pos(x,y,z-1),"-1 branch -Z %s\n");
			p_guess += D(x,y,z) + D(x,y,z-1);
		}
	}
	if (debug) fprintf(stderr,"---\n");
}

int ogp;
int orn;
int oo;

int randnodeiter(int x, int y, int z, int poss)
{
	oo = 0;

	// UP branch
	if ((y+1 < maxy) && ((ogp & UP) == 0) && (pos(x,y+1,z) == 0))
	{
		if (orn == 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);
			iterguess(x,y+1,z);
			return(0);
		}
		poss++;
	}
	// DOWN branch
	if ((y-1 >= 0) && ((ogp & DOWN) == 0) && (pos(x,y-1,z) == 0))
	{
		if (orn == 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);
			iterguess(x,y-1,z);
			return(0);
		}
		poss++;
	}
	// FORWARD branch
	if ((z+1 < maxz) && ((ogp & FWD) == 0) && (pos(x,y,z+1) == 0))
	{
		if (orn == 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);
			iterguess(x,y,z+1);
			return(0);
		}
		poss++;
	}
	// BACK branch
	if ((z-1 >= 0) && ((ogp & BACK) == 0) && (pos(x,y,z-1) == 0))
	{
		if (orn == 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);
			iterguess(x,y,z-1);
			return(0);
		}
		poss++;
	}
	// RIGHT branch
	if ((x+1 < maxx) && ((ogp & RIGHT) == 0) && (pos(x+1,y,z) == 0))
	{
		if (orn == 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);
			iterguess(x+1,y,z);
			return(0);
		}
		poss++;
	}
	// LEFT branch
	if ((x-1 >= 0) && ((ogp & LEFT) == 0) && (pos(x-1,y,z) == 0))
	{
		if (orn == 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);
			iterguess(x-1,y,z);
			return(0);
		}
		poss++;
	}
	oo = 1;
	return(poss);
}

int randnodedens(int x, int y, int z, int poss)
{
	int	a;

	oo = 0;

	// RIGHT branch
	if ((x+1 < maxx) && ((ogp & RIGHT) == 0) && (pos(x+1,y,z) == 0))
	{
		a = poss + D(x,y,z) + D(x+1,y,z);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,RIGHT);
			return(0);
		}
		poss = a;
	}
	// LEFT branch
	if ((x-1 >= 0) && ((ogp & LEFT) == 0) && (pos(x-1,y,z) == 0))
	{
		a = poss + D(x,y,z) + D(x-1,y,z);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,LEFT);
			return(0);
		}
		poss = a;
	}
	// UP branch
	if ((y+1 < maxy) && ((ogp & UP) == 0) && (pos(x,y+1,z) == 0))
	{
		a = poss + D(x,y,z) + D(x,y+1,z);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,UP);
			return(0);
		}
		poss = a;
	}
	// DOWN branch
	if ((y-1 >= 0) && ((ogp & DOWN) == 0) && (pos(x,y-1,z) == 0))
	{
		a = poss + D(x,y,z) + D(x,y-1,z);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,DOWN);
			return(0);
		}
		poss = a;
	}
	// FORWARD branch
	if ((z+1 < maxz) && ((ogp & FWD) == 0) && (pos(x,y,z+1) == 0))
	{
		a = poss + D(x,y,z) + D(x,y,z+1);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,FWD);
			return(0);
		}
		poss = a;
	}
	// BACK branch
	if ((z-1 >= 0) && ((ogp & BACK) == 0) && (pos(x,y,z-1) == 0))
	{
		a = poss + D(x,y,z) + D(x,y,z-1);
		if (orn >= poss && orn <= a)
		{
			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);
			densguess(x,y,z,BACK);
			return(0);
		}
		poss = a;
	}
	oo = 1;
	return(poss);
}

int randnode(void)
{
	int	x,y,z;
	int	poss;
	int	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;
		}
	}

	if (dens)
		poss = poss_count();
	else
		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...
	 */
	orn = RANDOM(0,poss);

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

	if (dens)
	{
		poss = 0;
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			if (((ogp = pos(x,y,z)) & CENTER) && ((ogp & dSTATIC) == 0))
			{
				poss = randnodedens(x,y,z,poss);
				if (oo == 0)
					return(0);
			}
		}
	}
	else
	{
		poss = 0;
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			if (((ogp = pos(x,y,z)) & CENTER) && ((ogp & dSTATIC) == 0))
			{
				poss = randnodeiter(x,y,z,poss);
				if (oo == 0)
					return(0);
			}
		}
	}
	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 x, int y, int z, int scale, int size, char *texture)
{
	fprintf(inc,"box { < %i, %i, %i > < %i, %i, %i > %s }\r\n",
		x*scale,y*scale,z*scale,
		x*scale+size,y*scale+size,z*scale+size,
		texture);
}

void makeboxw(FILE *inc, int x, int y, int z, double scale, double size, char *texture)
{
	fprintf(inc,"box { < %f, %f, %f > < %f, %f, %f > %s }\r\n",
		x*scale,y*scale,z*scale,
		x*scale+size,y*scale+size,z*scale+size,
		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;
	}
}

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,pw,foldmax;
	int	i,cut,cutpc,cutframe;
	int	x,y,z,max,o;
	double	cutd;
	double	wd;
	int	plist[256];
	int	pff,fd;

	srand(RANDSEED);

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

	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;
			else
			if (!strcmp(pt,"-foldmax"))
				foldmax = 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 'S':
				pt++;
				slice = atoi(pt);
				break;
			case 'L':
				logo++;
				break;
			case 'I':
				pt++;
				innerlight = atoi(pt);
				break;
			case 'D':
				debug = 1;
				break;
			case 'W':
				pt++;
				fd = open(pt,O_RDONLY);
				if (fd >= 0)
				{
					read(fd,plist,256*sizeof(int));
					close(fd);
					pff = 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 (plasma)
	{
		char	tx[100];
		double	col;
		FILE	*inc;
		int	f,pmin,pmax;

		if (plasmamutator <= 0)
			plasmamutator = 255;

		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);

		/*
		 *  put all numbers between min(1) and max(255)
		 */
		if (foldmax)
		for(f=1;f;)
		{
			f = 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)
				{
					f = 1;
					pos(x,y,z) = -pos(x,y,z);
				}
				if (pos(x,y,z) > 255)
				{
					f = 1;
					pos(x,y,z) = 511 - pos(x,y,z);
				}
			}
			if (f == 0)
				break;
			fprintf(stderr,"Plasma folded...\r\n");
		}

		pmin = pmax = pos(0,0,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 > pmax)
				pmax = f;
			if (f < pmin)
				pmin = f;
		}
		pmin = abs(pmin);
		pmax = pmax + pmin;
		for(x=0;x<maxx;x++)
		for(y=0;y<maxy;y++)
		for(z=0;z<maxz;z++)
		{
			f = pmin + pos(x,y,z);
			f = (254 * f) / pmax;
			if (pff >= 0)
				f = plist[f];
			pos(x,y,z) = f + 1;
		}

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

		if (slice == 1)
		{
		
			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++)
				{
					col = pos(x,y,z) / 255.0;
					sprintf(tx,"texture { pigment { color rgb < %f, %f, %f > }}",
						col,col,col);
					makeboxtx(inc,x,y,z,SCALE,SCALE,tx);
				}
			}
		}
		else
		if (slice == 0)
		{
			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)
				{
					col = pos(x,y,z) / 255.0;
					sprintf(tx,"texture { pigment { color rgb < %f, %f, %f > }}",
						col,col,col);
					makeboxtx(inc,x,y,z,SCALE,SCALE,tx);
					o++;
				}
			}
			fprintf(stderr,"Plasma: %i objects written (out of %i)\n",
				o,(maxx*maxy*maxz));
		}
		else
		if (slice == 3)
		{
			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++)
			{
				col = 1.0 - (pos(x,y,z) / 255.0);
				if (col <= PTC)
				{
					sprintf(tx,"texture { pigment { color rgbt < 1, 1, 1, %f > }}",col);
					makeboxtx(inc,x,y,z,SCALE,SCALE,tx);
					o++;
				}
			}
			fprintf(stderr,"Plasma: %i objects written (out of %i)\n",
				o,(maxx*maxy*maxz));
		}
		else
		if (slice == 2)
		{
			strcpy(tx,"texture { pigment { color rgb < 0.8, 0.4, 1.0 > }}");
			wd = (maxx / 256.0) * SCALE;
			for(x=0;x<256;x++)
			{
				makeboxw(inc,x,plist[x],maxz,wd,wd,tx);
			}
		}
		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);

		dens = grid;
		grid = calloc(1,maxx*maxy*maxz*2);
	}

	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 (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 (debug) fprintf(stderr,"Cutpc %i, Cutframe %i, PCDone %i, PCCount %i \r\n",
		cutpc,cutframe,pcdone,pccount);
	if (cutpc >= 0 && pcdone >= cutpc)
	{
		render();
		exit(0);
	}
	if (cutframe >= 0 && pccount >= cutframe)
	{
		render();
		exit(0);
	}

	if (debug) fprintf(stderr,"Building Nodes...\r\n");
	while(randnode() == 0)
	{
		pccount++;

		if (cutpc >= 0 && pcdone >= cutpc)
			break;
		if (cutframe >= 0 && pccount >= cutframe)
			break;
	}
	fprintf(stderr,"\r\n");
	if (debug) fprintf(stderr,"Empty nodes: %i\r\n",emptycount());

        max = maxx*maxy*maxz;

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

		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);
}
