Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
Darkhaven

Random Maze Generator (ZHeretic)

Recommended Posts

http://rapidshare.de/files/15202546/hereticGen.zip.html
(Play this with ZHeretic 2.0.63a. This is ZDoom v2.0.63a running with HERETIC.WAD. I built this WAD using the EXTENDED version of Heretic, which has five episodes. It shouldn't be a problem if you're running the three-episode version though.)

LAST UPDATE: The music selector code has been completely rewritten. It now (attempts to) randomly select a music lump that actually fits the theme. And on that subject, yet another theme has been added.

Not meant to be overly spectacular or fun, just a test script I wrote that builds a random "maze" (albeit a really simple one) for the hell of it. I got bored in class today and I happened to have DOOM Builder installed on one of the PC's in the computer lab, so here it is now.

Right now the script supports 4 basic themes, simple height variations, light shading (sort of), and sludge pits. It also generates a random name for the map at the start.

For the convenience of the more technical DOOMers, I included the SCRIPTS lump fully intact in the WAD and you're free to use this however you want (if you actually find uses for it), just please credit me somehow.

Tell me what you guys think could be done with this kind of stuff... Maybe something cool will come of it.

And if you don't feel like mucking around in the WAD to retrieve my SCRIPTS lump, here it is in it's entirety.

#include "zcommon.acs"

#define GRAYSTONE 0
#define LITESTONE 1
#define CELTIC    2
#define SAND      3
#define BLUE	  4
#define CAVERNS	  5

str NAME1[6] = {"Demon", "Dark", "Stagnant", "Abhorrant", "Foetid", "Haunted"};
str NAME2[5] = {"Crucible", "Cells", "Dungeon", "Tunnels", "Trench"};

str GRAYSTONE_MUS[9] = {"MUS_E1M1", "MUS_E1M2", "MUS_E1M3", "MUS_E1M4", "MUS_E1M5", "MUS_E1M6", "MUS_E1M7", "MUS_E1M8", "MUS_E1M9"};
str LITESTONE_MUS[3] = {"MUS_E1M7", "MUS_E1M3", "MUS_E2M3"};
str CELTIC_MUS[4] = {"MUS_E2M1", "MUS_E1M1", "MUS_E1M2", "MUS_E1M9"};
str SAND_MUS[5] = {"MUS_E3M3", "MUS_E1M1", "MUS_E1M2", "MUS_E1M4", "MUS_E2M2"};
str BLUE_MUS[3] = {"MUS_E3M2", "MUS_E2M6", "MUS_E1M2"};
str CAVERNS_MUS[2] = {"MUS_E2M1", "MUS_E2M2"};

int CaseOfMap;

int MUSICTHEME;
int SELECTED_MUSIC;

int primarytexture;
int secondarytexture;
int detailtexture;
int uppertexture;

int FLOORFLAT;
int CEILINGFLAT;
int UPPERFLAT;
int TERRAINFLAT;

int THEME;

int UPPERSHADE;

function void HeightVariation(void)
{
	switch(random(0, 3))
	{
		case 0:
		Ceiling_LowerInstant(0, 0, 1);
		ChangeCeiling(0, UPPERFLAT);
		Break;
		case 1:
		Ceiling_LowerInstant(1, 0, 1);
		ChangeCeiling(1, UPPERFLAT);
		Break;
		case 2:
		Ceiling_LowerInstant(2, 0, 1);
		ChangeCeiling(2, UPPERFLAT);
		case 3:
		Ceiling_LowerInstant(3, 0, 1);
		ChangeCeiling(3, UPPERFLAT);
		Break;
	}
}

function void CreateShadingTable(void)
{

	Light_Fade(0, random(128, 255), 1);
	Light_Fade(1, random(128, 255), 1);
	Light_Fade(2, random(128, 255), 1);
	Light_Fade(3, random(128, 255), 1);
	Light_Fade(4, random(128, 255), 1);
	Light_Fade(5, random(128, 255), 1);
	Light_Fade(6, random(128, 255), 1);
	Light_Fade(7, random(128, 255), 1);
	Light_Fade(8, random(128, 255), 1);
	Light_Fade(9, random(128, 255), 1);
	if(UPPERSHADE == 0)
		Light_Fade(100, random(0, 128), 1);
	else if(UPPERSHADE == 1)
		Light_Fade(101, random(0, 128), 1);
	else if(UPPERSHADE == 2)
		Light_Fade(102, random(0, 128), 1);
	else if(UPPERSHADE == 3)
		Light_Fade(103, random(0, 128), 1);
}

function void MakeItems(void)
{

	Thing_Move(100, random(1, 64));
	Thing_Move(101, random(1, 64));
	Thing_Move(102, random(1, 64));
	Thing_Move(103, random(1, 64));
	Thing_Move(104, random(1, 64));
	Thing_Move(105, random(1, 64));
	Thing_Move(106, random(1, 64));
	Thing_Move(107, random(1, 64));
	Thing_Move(108, random(1, 64));
	Thing_Move(109, random(1, 64));
	Thing_Move(110, random(1, 64));
	Thing_Move(111, random(1, 64));

}

function void MakeEnemies(void)
{

	Thing_Move(201, random(1, 64));
	Thing_Move(202, random(1, 64));
	Thing_Move(203, random(1, 64));
	Thing_Move(204, random(1, 64));
	Thing_Move(205, random(1, 64));

}

function void GenerateTextures(void)
{

	switch(random(0, 5))
	{
		case 0:
		THEME = GRAYSTONE;
		Break;
		case 1:
		THEME = LITESTONE;
		Break;
		case 2:
		THEME = CELTIC;
		case 3:
		THEME = SAND;
		Break;
		case 4:
		THEME = BLUE;
		Break;
		case 5:
		THEME = CAVERNS;
		Break;
	}
	if(THEME == GRAYSTONE)
	{
		primarytexture = "GRSTNPB";
		secondarytexture = "SQPEB1";
		detailtexture = "METL2";
		uppertexture = "METL2";
		FLOORFLAT = "FLAT523";
		CEILINGFLAT = "FLOOR03";
		UPPERFLAT = "FLOOR28";
		TERRAINFLAT = "FLTWAWA1";
	}
	else if(THEME == LITESTONE)
	{
		primarytexture = "TRISTON1";
		secondarytexture = "GRSTNPB";
		detailtexture = "METL2";
		uppertexture = "WOODWL";
		FLOORFLAT = "FLAT521";
		CEILINGFLAT = "FLAT503";
		UPPERFLAT = "FLOOR10";
		TERRAINFLAT = "FLTSLUD1";
	}
	else if(THEME == CELTIC)
	{
		primarytexture = "CELTIC";
		secondarytexture = "CELTIC";
		detailtexture = "WOODWL";
		uppertexture = "METL2";
		FLOORFLAT = "FLAT522";
		CEILINGFLAT = "FLAT506";
		UPPERFLAT = "FLOOR30";
		TERRAINFLAT = "FLTLAVA1";
	}
	else if(THEME == SAND)
	{
		primarytexture = "SPINE2";
		secondarytexture = "SNDBLCKS";
		detailtexture = "METL2";
		uppertexture = "SPINE2";
		FLOORFLAT = "FLAT522";
		CEILINGFLAT = "FLOOR25";
		UPPERFLAT = "FLOOR25";
		TERRAINFLAT = "FLTSLUD1";
	}
	else if(THEME == BLUE)
	{
		primarytexture = "MOSAIC1";
		secondarytexture = "BLUEFRAG";
		detailtexture = "METL2";
		uppertexture = "METL2";
		FLOORFLAT = "FLOOR07";
		CEILINGFLAT = "FLAT502";
		UPPERFLAT = "FLOOR29";
		TERRAINFLAT = "FLTWAWA1";
	}
	else if(THEME == CAVERNS)
	{
		primarytexture = "LAVA1";
		secondarytexture = "LOOSERCK";
		detailtexture = "METL2";
		uppertexture = "LOOSERCK";
		FLOORFLAT = "FLAT509";
		CEILINGFLAT = "FLAT523";
		UPPERFLAT = "FLAT510";
		TERRAINFLAT = "FLTLAVA1";
	}
	MUSICTHEME = THEME;
}

function void MakeThemeTextures(void)
{
	SetLineTexture(1, SIDE_FRONT, TEXTURE_BOTTOM, primarytexture);
	SetLineTexture(1, SIDE_BACK, TEXTURE_BOTTOM, primarytexture);
	SetLineTexture(1, SIDE_FRONT, TEXTURE_TOP, uppertexture);
	SetLineTexture(1, SIDE_BACK, TEXTURE_TOP, uppertexture);
	SetLineTexture(2, SIDE_FRONT, TEXTURE_MIDDLE, secondarytexture);
	SetLineTexture(2, SIDE_BACK, TEXTURE_MIDDLE, secondarytexture);
	ChangeFloor(0, FLOORFLAT);
	ChangeFloor(1, FLOORFLAT);
	ChangeFloor(2, FLOORFLAT);
	ChangeFloor(3, FLOORFLAT);
	ChangeFloor(4, FLOORFLAT);
	ChangeFloor(5, FLOORFLAT);
	ChangeFloor(6, FLOORFLAT);
	ChangeFloor(7, FLOORFLAT);
	ChangeFloor(8, FLOORFLAT);
	ChangeFloor(9, FLOORFLAT);
	ChangeCeiling(0, CEILINGFLAT);
	ChangeCeiling(1, CEILINGFLAT);
	ChangeCeiling(2, CEILINGFLAT);
	ChangeCeiling(3, CEILINGFLAT);
	ChangeCeiling(4, CEILINGFLAT);
	ChangeCeiling(5, CEILINGFLAT);
	ChangeCeiling(6, CEILINGFLAT);
	ChangeCeiling(7, CEILINGFLAT);
	ChangeCeiling(8, CEILINGFLAT);
	ChangeCeiling(9, CEILINGFLAT);
}

function void MakeMap(void)
{
	switch(random(0, 7))
	{
		case 0:
		Floor_RaiseInstant(random(0, 2), 0, 9);
		Floor_RaiseInstant(random(3, 6), 0, 9);
		CaseOfMap = 0;
		Break;
		case 1:
		Floor_RaiseInstant(random(2, 4), 0, 9);
		Floor_RaiseInstant(random(7, 10), 0, 9);
		CaseOfMap = 1;
		Break;
		case 2:
		Floor_RaiseInstant(random(0, 4), 0, 9);
		Floor_RaiseInstant(random(5, 9), 0, 9);
		CaseOfMap = 2;
		Break;
		case 3:
		Floor_RaiseInstant(random(3, 5), 0, 9);
		Floor_RaiseInstant(random(6, 10), 0, 9);
		CaseOfMap = 3;
		Break;
		case 4:
		Floor_RaiseInstant(random(0, 3), 0, 9);
		Floor_RaiseInstant(random(5, 10), 0, 9);
		CaseOfMap = 4;
		Break;
		case 5:
		Floor_RaiseInstant(random(4, 6), 0, 9);
		Floor_RaiseInstant(random(7, 9), 0, 9);
		CaseOfMap = 5;
		Break;
		case 6:
		Floor_RaiseInstant(random(0, 4), 0, 9);
		Floor_RaiseInstant(random(8, 10), 0, 9);
		CaseOfMap = 6;
		Break;
		case 7:
		Floor_RaiseInstant(random(3, 7), 0, 9);
		Floor_RaiseInstant(random(8, 10), 0, 9);
		CaseOfMap = 7;
		Break;
	}
	MakeThemeTextures();
}

function void DoDetail(void)
{

	switch(random(0, 3))
	{
		case 0:
		Floor_RaiseInstant(200, 0, 8);
		Floor_RaiseInstant(201, 0, 8);
		Ceiling_LowerInstant(100, 0, 4);
		UPPERSHADE = 0;
		Break;
		case 1:
		Floor_RaiseInstant(201, 0, 8);
		Floor_RaiseInstant(202, 0, 8);
		Ceiling_LowerInstant(101, 0, 4);
		UPPERSHADE = 1;
		Break;
		case 2:
		Floor_RaiseInstant(202, 0, 8);
		Floor_RaiseInstant(203, 0, 8);
		Ceiling_LowerInstant(102, 0, 4);
		UPPERSHADE = 2;
		Break;
		case 3:
		Floor_RaiseInstant(203, 0, 8);
		Floor_RaiseInstant(204, 0, 8);
		Ceiling_LowerInstant(103, 0, 8);
		UPPERSHADE = 3;
		Break;
	}
	SetLineTexture(3, SIDE_FRONT, TEXTURE_BOTTOM, detailtexture);
	SetLineTexture(3, SIDE_BACK, TEXTURE_BOTTOM, detailtexture);
	SetLineTexture(4, SIDE_FRONT, TEXTURE_BOTTOM, detailtexture);
	SetLineTexture(4, SIDE_BACK, TEXTURE_BOTTOM, detailtexture);
	SetLineTexture(100, SIDE_FRONT, TEXTURE_TOP, uppertexture);
	SetLineTexture(100, SIDE_BACK, TEXTURE_TOP, uppertexture);

}	

function void SetupMusic(void)
{
	switch(MUSICTHEME)
	{
		case 0:
		SELECTED_MUSIC = GRAYSTONE_MUS[random(1, 9)];
		Break;
		case 1:
		SELECTED_MUSIC = LITESTONE_MUS[random(1, 3)];
		Break;
		case 2:
		SELECTED_MUSIC = CELTIC_MUS[random(1, 4)];
		Break;
		case 3:
		SELECTED_MUSIC = SAND_MUS[random(1, 5)];
		Break;
		case 4:
		SELECTED_MUSIC = BLUE_MUS[random(1, 3)];
		Break;
		case 5:
		SELECTED_MUSIC = CAVERNS_MUS[random(1, 2)];
		Break;
	}
	SetMusic(SELECTED_MUSIC, 0);
}

function void MakeSlime(void)
{

	switch(random(0, 9))
	{
	
		case 0:
		Floor_LowerInstant(0, 0, 1);
		ChangeFloor(0, TERRAINFLAT);
		Break;
		case 1:
		Floor_LowerInstant(1, 0, 1);
		ChangeFloor(1, TERRAINFLAT);
		Break;
		case 2:
		Floor_LowerInstant(2, 0, 1);
		ChangeFloor(2, TERRAINFLAT);
		Break;
		case 3:
		Floor_LowerInstant(3, 0, 1);
		ChangeFloor(3, TERRAINFLAT);
		Break;
		case 4:
		Floor_LowerInstant(4, 0, 1);
		ChangeFloor(4, TERRAINFLAT);
		Break;
		case 5:
		Floor_LowerInstant(5, 0, 1);
		ChangeFloor(5, TERRAINFLAT);
		Break;
		case 6:
		Floor_LowerInstant(6, 0, 1);
		ChangeFloor(6, TERRAINFLAT);
		Break;
		case 7:
		Floor_LowerInstant(7, 0, 1);
		ChangeFloor(7, TERRAINFLAT);
		Break;
		case 8:
		Floor_LowerInstant(8, 0, 1);
		ChangeFloor(8, TERRAINFLAT);
		Break;
		case 9:
		Floor_LowerInstant(9, 0, 1);
		ChangeFloor(9, TERRAINFLAT);
		Break;
	}

}

function void DoSkyBox(void)
{

	switch(random(0, 9))
	{
		case 0:
		Ceiling_RaiseInstant(0, 0, 2);
		ChangeCeiling(0, "F_SKY1");
		Break;
		case 1:
		Ceiling_RaiseInstant(1, 0, 2);
		ChangeCeiling(1, "F_SKY1");
		Break;
		case 2:
		Ceiling_RaiseInstant(2, 0, 2);
		ChangeCeiling(2, "F_SKY1");
		Break;
		case 3:
		Ceiling_RaiseInstant(3, 0, 2);
		ChangeCeiling(3, "F_SKY1");
		Break;
		case 4:
		Ceiling_RaiseInstant(4, 0, 2);
		ChangeCeiling(4, "F_SKY1");
		Break;
		case 5:
		Ceiling_RaiseInstant(5, 0, 2);
		ChangeCeiling(5, "F_SKY1");
		Break;
		case 6:
		Ceiling_RaiseInstant(6, 0, 2);
		ChangeCeiling(6, "F_SKY1");
		Break;
		case 7:
		Ceiling_RaiseInstant(7, 0, 2);
		ChangeCeiling(7, "F_SKY1");
		Break;
		case 8:
		Ceiling_RaiseInstant(8, 0, 2);
		ChangeCeiling(8, "F_SKY1");
		Break;
		case 9:
		Ceiling_RaiseInstant(9, 0, 2);
		ChangeCeiling(9, "F_SKY1");
		Break;
	}
}
	

Script 1 OPEN
{

	SetUpMusic();
	GenerateTextures();
	MakeMap();
	DoDetail();
	CreateShadingTable();
	MakeItems();
	MakeEnemies();
	Thing_Move(200, random(1, 64));
	switch(random(0, 3))
	{
		case 0:
		Break;
		case 1:
		MakeSlime();
		HeightVariation();
		Break;
		case 2:
		MakeSlime();
		DoSkyBox();
		Break;
		case 3:
		DoSkyBox();
		Break;
	}
	SetFont("HBIGFONT");
	HudMessage(s:"Welcome to the ", s:NAME1[random(2,6)], s:" ", s:NAME2[random(1,5)], s:"..."; 2, 300, CR_RED, 0.5, 0.5, 1);
	Delay(5);
	Floor_LowerByValue(10, 5, 128);

}

Script 2 (void) //Bind a key to "puke 2" if the music selector fucks up and thinks "demon" is a music lump.
{

	SetUpMusic();

}
As you can tell this script could be cleaned up massively, and if you look closely, there's a half-completed function somewhere in the middle that references "DoDetail". This feature is incomplete but it might be in the next version of the Maze Generator if I feel like it. Also, if any of you guys are really good with ACS, any help with making this messy script better or just more "streamlined" would be appreciated.

LAST UPDATE: The music selector code has been completely rewritten. It now (attempts to) randomly select a music lump that actually fits the theme. And on that subject, yet another theme has been added.

BUGS THAT I KNOW about : Sometimes the music selection function fucks up and thinks "demon" (which is actually not even in any of the music stringtables) is a music lump that can be selected and used. Fix: Bind the command "puke 2" to any key and the music selector routine will be run again and hopefully you'll get a track that you like.

Share this post


Link to post

That is pretty cool. Were you inspired by the MAP41 hidden in Hexen 1.0 (later removed in 1.1)?

One thing I'd recommend is altering the thing placement routine so that it checks and makes sure not to place things in sectors that are acting as walls.

I'm interested to see how you develop this further, if you do.

Share this post


Link to post

Actually I never noticed that MAP41 existed in Hexen 1.0, but I do have a 1.0 IWAD. I'll check it out. I was inspired by Doom - The RogueLike (http://doom.chaosforge.org).

As for altering the thing placing routine, I've had trouble during the short development cycle of this map trying to figure out how I could go about implementing "collision detection" for the items and enemies. The way it is now, some items will appear on the map and some will not (to add to the randomness of the "maze"), so I'm not sure if I want to do it or not. Nonetheless, if anyone has any ideas how smart thing placement could be implemented, it would be a big help.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×