Page 1 of 1

Procedural map generation

PostPosted: Sat Aug 20, 2016 2:30 pm
by zoaedk
As I was looking around the Nox code, I stumbled across the map generation stuff again. This time I actually took some time to understand it. Below are instructions for using Nox's built-in map generation.

First thing to understand is that the map generation requires a theme file. The complete syntax is a little verbose, but the sample theme file below gives you an idea. I will try to completely document the syntax later.

The theme file is encrypted, just like many other Nox files. I wrote a quick python script ( ... xcrypt.exe) which you can use to encrypt theme files.

Once it is encrypted, save the theme into \mapgen\, you should load up Nox; and make sure that it is Administrator or has permissions to write to \maps\. Start a Local Network, multiplayer game, and in the console type:
Code: Select all
load #foobar

Obviously, you should change the foobar part to the name of your theme file. The # is what indicates that you want to generate a map instead of loading a normal map. If everything goes smoothly, you will now be in your new map and it will have been saved in your maps folder as $foobar.

Sample theme file (foobar.thm)
Code: Select all
// This file should be encrypted then saved in your Nox directory as \mapgen\foobar.thm. The filename determines the map name. Keep under 8 chars.

AMBIENT_LIGHT 255 255 255

    ROOM foo
    WALL_FLOOR AncientRuin AncientRuin

    HALL bar
    WALL_FLOOR AncientRuin AncientRuin

// End of file

Sample theme file with sample generated map is attached.

Re: Procedural map generation

PostPosted: Sat Aug 20, 2016 4:19 pm
by Xandros
Wait. Map generator in Nox is working??? I heard that map generator consists mostly of stubs and unfinished code chunks...

Re: Procedural map generation

PostPosted: Sun Aug 21, 2016 5:25 am
by zoaedk
I previously thought that it was hopeless as well. But apparently I just wasn't good enough previously to understand how it works.

That said, this is not sufficient for making a good map. It could be useful though to create an initial map with doors, tiles, walls, etc., which someone could then tweak and improve in the map editor.

Once I finish the scripting stuff I'm focusing on, I'll poke at this some more.

Re: Procedural map generation

PostPosted: Mon Aug 22, 2016 5:12 am
by superjack46
By the way, KirC also implemented a map generator in the map editor. You can check it in the newest version, just press F7.

Brilliant stuff though, zoa.

Re: Procedural map generation

PostPosted: Mon Aug 22, 2016 12:56 pm
by Xandros
Wow. Thank you for figuring out how it works. I will use it someday.

Re: Procedural map generation

PostPosted: Wed Aug 24, 2016 2:34 pm
by angrykirc
just my 5 cents, some old research
Code: Select all
// 0x004D4320
BOOL __cdecl mapGenStart()
// 0x004D5F30
BOOL __cdecl mapGenStartAlt()
// 0x0051E540
BOOL __cdecl mapGenReadLine(FILE *File, char *out)
// 0x0051E260
BOOL __cdecl mapGenReadTheme(mapGenTheme *data, char *configFile)
// 0x004D44E0
BOOL __cdecl mapGenStep()
// 0x00526AC0
int __cdecl mapGenRandFunc(int min, int max)
void __cdecl mapGenFreeTopRoom()
// 0x00521710
mapGenWorkRoom *__cdecl mapGenGetTopRoom()
// 0x00521940
mapGenWorkRoom *__cdecl mapGenMakeRoomStruct(signed int x, signed int y)
// 0x00521730
int __cdecl mapGenAddNewRoom(mapGenWorkRoom *newr)
// 0x00526830
BOOL __cdecl mapGenPlacePrefabs(mapGenTheme *theme)
// 0x00524310
BOOL __cdecl mapGenMakeRooms(mapGenTheme *theme)
// 0x00522A40
BOOL __cdecl mapGenMakeExit(mapGenTheme *theme)
// 0x00521990
mapGenWorkRoom *__cdecl mapGenPrepareRoom(mapGenTheme *theme)
// 0x004D4F40
mapGenWorkRoom *__cdecl mapGenMkSmallRoom(mapGenTheme *theme)
// 0x00521880
mapGenWorkRoom *__cdecl mapGenSetRoomPos(mapGenWorkRoom *room, float *coords)
// 0x00521850
mapGenWorkRoom *__cdecl mapGenUpdateRoomRect(mapGenWorkRoom *room)
// 0x005238F0
BOOL __cdecl mapGenCheckRoomType(mapGenWorkRoom *room)
// 0x005220E0
bigUnitStruct *__cdecl mapGenMakeSpellbook(mapGenTheme *theme, const char *name)
// 0x00522810
bigUnitStruct *__cdecl mapGenMakeMonsterInRoom(mapGenWorkRoom *room, char *name)
// 0x00527940
BOOL __cdecl mapGenGetObjID(char *Key)
// 0x005279B0
bigUnitStruct *__cdecl mapGenPlaceObj(float *coords)
// 0x00527A10
bigUnitStruct *__cdecl mapGenMoveObject(bigUnitStruct *Unit, float *coords)
// 0x00527C60
BOOL __cdecl mapGenOrientObj(bigUnitStruct *obj, int dir)
// 0x004D3D90
BOOL __cdecl mapGenFixCoords(float *a1, float *a2)

// 0x0074EB78 mapGenTheme (full struct)
// 0x00833A9C mapGenWorkRoom*
// 0x0074EFD4 mapGenWorkRoom*
// 0x0074EFD8 mapGenWorkRoom*
// 0x00833AAC mapGenWorkRoom*

struct mapGenTheme
  int skeleton;
  int midHallLength;
  int hallLengthVariance;
  int midHallWidth;
  int hallWidthVariance;
  int hallLimit;
  int hallBranchRate;
  int hallRoomRate;
  int midRoomSize;
  int roomVariance;
  int irregularRoomRate;
  int emptyRoomRate;
  int mergeRate;
  int adjacentPortalRate;
  int useDoors;
  int debug;
  int mapSize;
  float smallMapSize;
  int recursionLimit;
  int seed;
  int prefabStructPtr;
  int prefabCounter;
  mapGenDecorStruct *roomDecorStruct;
  int roomDecorCounter;
  char unkBlock1[24];
  mapGenDecorStruct *hallDecorStruct;
  int hallDecorCounter;
  char unkBlock2[24];
  mapGenDecorStruct *templateDecorStruct;
  int templateDecorCounter;
  char unkBlock3[24];
  mapGenDecorStruct *backdropDecorStruct;
  int backdropDecorCounter;
  char unkBlock4[24];
  char mapExitA[64];
  char mapExitB[64];
  char mapExitC[64];
  char mapExitD[64];
  char mapExitE[64];
  int ambLightR;
  int ambLightG;
  int ambLightB;
  int spellList[137];
  int spellListCounter;
  int lastWeaponSet;
  int weaponSetCounter;
  int lastArmorSet;
  int armorSetCounter;

struct mapGenDecorStruct
  char decorTypeStr[60];
  int decorTypeId;
  char occurConstraint;
  char occurLimit;
  char unknownBool;
  char decorMustOccur;
  char generated;
  char unusedAlign1;
  char unusedAlign2;
  char unusedAlign3;
  int frequency;
  int roomSizeMin;
  int roomSizeMax;
  mapGenWallFloorData *wallFloorDataPtr;
  int wallFloorCounter;
  mapGenDecorSetData *decorSetDataPtr;
  int decorSetCounter;
  char doorThingName[60];
  char doubleDoorThingName[60];
  mapGenDecorStruct *prevStructPtr;

struct mapGenWallFloorData
  char wallTypeStr[60];
  char floorTypeStr[60];
  int unused;
  mapGenWallFloorData *prevStructPtr;

struct mapGenDecorSetData
  int int1;
  int int2;
  mapGenDecorElement *lastElement;
  int elementCounter;
  int unknown1;
  int unknown2;

struct mapGenDecorElement
  int elementTypeId;
  char unkString[60];
  int unkBool;
  int unkCount;
  int unkInt2;
  float unkFloat;
  int unused1;
  int unused2;
  mapGenDecorElement *prevElementPtr;
  int unused3;
  int unused4;

struct mapGenWeaponArmorSet
  char string1[60];
  char string2[60];
  int unknown1;
  int unknown2;
  int unknown3;
  int unknown4;
  int unknown5;
  int unknown6;
  int unknown7;
  int unknown8;
  mapGenWeaponArmorSet *prevStructPtr;

struct mapGenWorkRoom
  int type;
  int wallPosX;
  int wallPosY;
  int wallSizeX;
  int wallSizeY;
  float fltPosX;
  float fltPosY;
  float sizeX;
  float sizeY;
  float fltRectX;
  float fltRectY;
  float fltRectRight;
  float fltRectDown;
  char unknown1[16];
  int flags;
  mapGenWorkRoom *prevRoom;
  mapGenWorkRoom *nextRoom;
  char unknown2[20];
  mapGenWorkRoom *branchMb;
  char unknown3[128];
  char unkArray[4];
  char unknown4[156];