Light Style© by Fisana

Jump to content


Photo

Where to share/upload random map generators


  • Please log in to reply
21 replies to this topic

#1 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 27 February 2012 - 11:55 PM

I wrote a random map generator and now want to know where to talk about it and where to share it if it's good enough.

I found it hard to find the things I need inside the code of the helper functions inside the "rmgen" directory. Is there a documentation or a small tutorial out there?

And what variables can be set in the .json file?

For those who have similar issues:
- The directory own scripts can be added and then work with the game and the editor in windows is (similar to the player made "scenarios" folder):
c:\users\[username]\AppData\Roaming\0ad\cache\mods\public\maps\random

Edited by FeXoR, 28 February 2012 - 12:09 AM.

  • 0

#2 historic_bruno

historic_bruno

    Primus Pilus

  • WFG Programming Team
  • 2,300 posts

Posted 28 February 2012 - 12:34 AM

It's all fairly well documented on Trac actually: http://trac.wildfire...m_Map_Generator

Except for the .json file, I don't see documentation for that yet :) Basically it follows the same format as scenarios, if you look in maps\scenarios\*.xml in the <scriptSettings> element, you will see for example:
{
  "CircularMap": true,
  "Description": "Arch enemies, Rome and Carthage, square off on a richly detailed map of Southern Italy.\u000a\u000aScout the lands to find free Treasures and to secure new resources.",
  "GameType": "conquest",
  "Keywords": [],
  "LockTeams": false,
  "Name": "Acropolis III",
  "PlayerData": [
    {
      "AI": "",
      "Civ": "rome",
      "Colour": {
        "b": 13,
        "g": 13,
        "r": 166
      },
      "Name": "Player 1",
      "Resources": {
        "food": 400,
        "wood": 400
      },
      "Team": -1
    },
    {
      "AI": "qbot",
      "Civ": "cart",
      "Colour": {
        "b": 168,
        "g": 64,
        "r": 55
      },
      "Name": "Player 2",
      "Resources": {
        "food": 400,
        "wood": 400
      },
      "Team": -1
    }
  ],
  "RevealMap": false
}

I'll try adding documentation about this.
  • 0
Ben Brian [ aka historic_bruno ]

Wildfire Games Programmer
Contact me: ben [at] wildfiregames [dot] com

#3 historic_bruno

historic_bruno

    Primus Pilus

  • WFG Programming Team
  • 2,300 posts

Posted 28 February 2012 - 02:10 AM

Documented the JSON here: http://trac.wildfire...#DefiningtheMap
  • 0
Ben Brian [ aka historic_bruno ]

Wildfire Games Programmer
Contact me: ben [at] wildfiregames [dot] com

#4 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 28 February 2012 - 02:26 AM

THX, that helps.

I made the different civil centers align to the diagonal grid that is used in-game for placing structures by default but roughly facing the center of the map (1*PI/4, 3*PI/4, 5*PI/4 and 7*PI/4).
I thought that wouldn't result in problems since a change of the wired const "BUILDING_ANGlE" (with a small written "L" ^^) did'nt change anything in-game (but the orientation of all map-generated buildings of cause).
So I made them different for each player and set them as a variable.
Well, but sometimes, often enough to occur 50% at 8 player maps, one or two civil centers are facing in a non-alligned directions (And some functions afterwards are not called).

Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"?



  • 0

#5 historic_bruno

historic_bruno

    Primus Pilus

  • WFG Programming Team
  • 2,300 posts

Posted 28 February 2012 - 11:11 PM

Is the orientation for buildings in general needed as a const or even need to be named "BUILDING_ANGlE"?

It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that :)). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.

Edit: Also AIs, I believe they layout their buildings in the same direction.
  • 0
Ben Brian [ aka historic_bruno ]

Wildfire Games Programmer
Contact me: ben [at] wildfiregames [dot] com

#6 Mythos_Ruler

Mythos_Ruler

    Megas Philhellene

  • 0 A.D. Project Leader
  • 14,873 posts

Posted 28 February 2012 - 11:37 PM

It's just the convention to have all the buildings facing in the same direction for aesthetic reasons, in other words facing towards the starting camera which is the same for all players (Mythos_Ruler was very insistent on that :)). That constant might be defined in each separate file, but it should be moved to the rmgen library instead.


It's also better for gameplay, so that there is a consistent exit point for units and a consistent start point for building rotation if players want units to exit in a different direction.
  • 0

Michael D. Hafer [aka Mythos_Ruler]

Wildfire Games Project Leader

Contact me: michaeldhafergmailcom

 

Support Wildfire Games!

 

10298.png


#7 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:27 AM

THX for the reply!

The problem was within my file and it's fixed now.
However, the building orientation IS inside the grid the AI and the start orientation in-game uses, but there are still the 4 possibilities.

Well, not a big issue since it works fine now.
I did many things very different then it is handled in the other RMGs.

Mine is a very early state until now and more for getting to know the functions, but if anyone wants to take a look:
fexor_rmg.rar
  • 0

#8 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:33 AM

Oh, and for those preferring .zip:
fexor_rmg.zip

EDIT: My dear, wrong version, now it should work... [hope]

Edited by FeXoR, 29 February 2012 - 12:51 AM.

  • 0

#9 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:39 AM

BTW! The mathematical orientation (defined by cos/sin in x/y direction) and the unit/building orientation differs.

I think unit orientation is:
-(mathematical orientation - PI/2)

How did that happen?

And why is the second vertical orientation named "z" instead of "y"?
I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?

Sorry, questions and more questions x)

Edited by FeXoR, 29 February 2012 - 12:43 AM.

  • 0

#10 historic_bruno

historic_bruno

    Primus Pilus

  • WFG Programming Team
  • 2,300 posts

Posted 29 February 2012 - 03:55 AM

And why is the second vertical orientation named "z" instead of "y"?
I thought "z" would be the hight over ground or to a base hight but in 0ad it's "y"?

That was just a choice made long ago and unlikely to change :) I've seen either Y or Z used as height equally in different applications (X could be used, too but that would be weird).
  • 0
Ben Brian [ aka historic_bruno ]

Wildfire Games Programmer
Contact me: ben [at] wildfiregames [dot] com

#11 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 11:25 AM

Sooo...

Here's a function to place civil center and starting units just by giving the location and the player index of the player the units should be placed for.
This is the (very) detailed version for (hopefully) good readability, a shorter version will be added:

// Funtion to place civil centre and starting units at given location for a given player
function placeStartUnits0adAlike(startLocation, playerId)
// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.
// "startLocation[0]" should be an float determining the x coordinate of the start location.
// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)
// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia)
{
	// Some checks. Enhance if needed...
	
	// Setting some variables
	// Setting default building angle
	var buildingAngle = 3*Math.PI/4;
	// Getting civilisation string
	var civ = g_MapSettings.PlayerData[i].Civ;
	// Getting civilisation dependent default starting entities
	var civEntities = g_CivData[civ].StartEntities;
	// Setting start tile. Not needed but done in the other RMGs so....
	var startTile = new Array(2)
	startTile[0]= round(startLocation[0])
	startTile[1]= round(startLocation[1])
	
	// Place civil centre on the start tile
	placeObject(startTile[0], startTile[1], civEntities[0].Template, playerId, buildingAngle);
	
	// Place starting units
	// Minimal distance to start location so that units don't stand in the civil centere
	var minDistToCC = 4;
	// Minimal distance between units so they don't overlap
	var minDist = 1;
	// Set general orientation of units
	var angleMain = -(buildingAngle - PI/2); // This is a bug in my book, it should be the same as building orientation...
	// Set angle width units should be spread over
	var angleSpread = PI/4;
	// Preset angle the first unit should be placed, reset in the outer loop
	var angleStart = angleMain - angleSpread/2;
	// Preset angle distance between one unit and the next of the same type, reset in the outer loop
	var angleAdd = 0;
	// Preset the angle a unit will be placed in comperison to the civil centre, reset inside the inner loop
	var angleActual = angleStart;
	// Preset number of units to place by default of the same type, reset in outer loop
	var numberOfUnitsOfSameType = 1;
	// Preset unit template, reset in the outer loop
	var unitTemplate = '';
	// Preset postition the unit will be placed, reset inside the inner loop
	var unitPosition = new Array(2);
	unitPosition[0] = startTile[0];
	unitPosition[1] = startTile[1];
	// Preset orientation of placed unit, reset in the inner loop
	var unitOrientation = 0;
	// Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1)
	for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex)
	{
		// Reset default number of units of that type
		numberOfUnitsOfSameType = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1);
		// Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision)
		if (numberOfUnitsOfSameType > 1) {angleAdd = angleSpread/(numberOfUnitsOfSameType-1)};
		// Reset unit tamplate
		unitTemplate = civEntities[unitTypeIndex].Template;
		// Inner loop for multiple units of the same type
		for (var unitIndex = 0; unitIndex < numberOfUnitsOfSameType; unitIndex++)
		{
			// Resetting the angle the unit 
			if (numberOfUnitsOfSameType > 1) {angleActual = angleStart + unitIndex*angleAdd}
			else {angleActual = angleMain};
			// Reset the angle the unit will be placed in comperison to the civil centre
			unitPosition[0] = startTile[0] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual);
			unitPosition[1] = startTile[1] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual);
			// Reset orientation of placed unit
			unitOrientation = -(angleActual - PI/2); // Here is the bug again...
			// Place the unit
			placeObject(unitPosition[0], unitPosition[1], unitTemplate, playerId, unitOrientation);
		};
	};
};
 
BTW, this does'nt seam to be a good place to put this, suggestions very welcome.P.S.: Did I mention this game is pure @#$%ing awesomeness?P.P.S.: Oh, I hope I did'nt break any forum rules now ;0|


  • 0

#12 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:00 PM

Got some strange formation issues in the post writer tool... well...

Here's a more reasonable version.
Swapped sin and cos so unit orientation and mathematical point calculation matches.
Still I think that's a little strange...
Many variables are set in the loop now with var over and over again... is this OK?
But it's much shorter now:

// Funtion to place civil centre and starting units at given location for a given player
function placeStartUnits(startLocation, playerId)
// "startLocation" should be a list of length 2 with floats determining the 2d-point where the starting entities shall be placed.
// "startLocation[0]" should be an float determining the x coordinate of the start location.
// "startLocation[1]" should be an float determining the z coordinate of the start location. (Should by y in my book though)
// "playerId" should be the player number like seen in Atlas or the game settings ingame (Starting with 1 for the first player with default colour blue, 0 is Gaia)
{
	// Some checks. Enhance if needed...
	
	// Setting some variables
	// Setting default building angle, can be got from the global "BUILDING_ANGlE" in further versions
	var buildingOrientation = 3*Math.PI/4;
	// Getting civilisation dependent default starting entities
	var civEntities = g_CivData[g_MapSettings.PlayerData[i].Civ].StartEntities;
	
	// Place civil centre on the start location
	placeObject(startLocation[0], startLocation[1], civEntities[0].Template, playerId, buildingOrientation);
	
	// Place starting units
	// Minimal distance to start location so that units don't stand in the civil centere
	var minDistToCC = 4;
	// Minimal distance between units so they don't overlap
	var minDist = 1;
	// Set angle width units should be spread over
	var angleSpread = PI/4;
	// Outer loop for the diffrent unit types to place beside the civil centre (so starting with 1)
	for (var unitTypeIndex = 1; unitTypeIndex < civEntities.length; ++unitTypeIndex)
	{
		// Reset default number of units of that type
		var unitCount = (civEntities[unitTypeIndex].Count !== undefined ? civEntities[unitTypeIndex].Count : 1);
		// Reset the angle added per unit of that type depending on the number of them, for multiple units of that type only (otherwise 0 devision)
		if (unitCount > 1) {var angleAdd = angleSpread/(unitCount-1)};
		// Inner loop for multiple units of the same type
		for (var unitIndex = 0; unitIndex < unitCount; unitIndex++)
		{
			// Resetting the angle the unit will be placed in comperison to the city centre
			if (unitCount > 1) {var angleActual = buildingOrientation - angleSpread/2 + unitIndex*angleAdd}
			else {var angleActual = buildingOrientation};
			// Place the unit
			placeObject(
				startLocation[0] + (minDistToCC + minDist*unitTypeIndex)*sin(angleActual),
				startLocation[1] + (minDistToCC + minDist*unitTypeIndex)*cos(angleActual),
				civEntities[unitTypeIndex].Template, playerId, angleActual);
		};
	};
};

  • 0

#13 Spahbod

Spahbod

    Triplicarius

  • WFG Programming Team
  • 572 posts

Posted 29 February 2012 - 12:07 PM

This function is already present in SVN version of the game. It now looks like this:

function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_ANGlE)
{
	var uDist = 6;
	var uSpace = 2;
	placeObject(fx, fz, civEntities[0].Template, playerid, BUILDING_ANGlE);
	for (var j = 1; j < civEntities.length; ++j)
	{
		var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;
		var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
		for (var numberofentities = 0; numberofentities < count; numberofentities++)
		{
			var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
			var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
			placeObject(ux, uz, civEntities[j].Template, playerid, (j % 2 - 1) * PI + uAngle);
		}
	}
}

  • 0
Omid Davoodi [ aka Spahbod ]

Wildfire Games Random Map Designer, Low-level Programmer
Contact me: myops37@yahoo.com


Support Wildfire Games!

#14 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:10 PM

I think something like that should be added to one of the rmgen .js files to make it easier for random map designers.
They still can make there own arrangements of starting units if they like.

Perhaps some value checks of function parameters should be added...
Perhaps the starting units should be placed right (female peasants), left (male peasants) and in front (Scout) to need less space (smaller maximum distance to start location).

Greetings U gorgeous bunch of individuals!

Oh, did'nt see this, thx!
  • 0

#15 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:13 PM

But you insist of define coordinated one by one.
Do you think that is wise?
Or tell me a reason?

Well, sry, your decision...
  • 0

#16 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 12:18 PM

Hehe, U made the same "mistake" like me.
Swap sin and cos ^^
  • 0

#17 Spahbod

Spahbod

    Triplicarius

  • WFG Programming Team
  • 572 posts

Posted 29 February 2012 - 01:29 PM

But you insist of define coordinated one by one.
Do you think that is wise?
Or tell me a reason?

Well, sry, your decision...

We want the function to be simple to use for new scripters. Also it is better to have a unified formation for all random maps.

Hehe, U made the same "mistake" like me.
Swap sin and cos ^^


:huh:
  • 0
Omid Davoodi [ aka Spahbod ]

Wildfire Games Random Map Designer, Low-level Programmer
Contact me: myops37@yahoo.com


Support Wildfire Games!

#18 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 02:49 PM

:huh:


To adjust the "build in" unit orientation of all (I guess) entity placement functions to the "usually" used determination of the unit position in polar coordinates (by distance and angle to the position of the civil center with cos/sin for x/y) it is adjusted by inverting the angle:

var uAngle = -BUILDING_ANGlE + PI * (j - 1) / 2;

Note the "-" in front of "BUILDING_ANGlE".

...and then adding (or subtract dependent of the braces used) PI/2:

var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
                        var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));

Note the "uAngle + PI/2" in cos/sin.

But it can be done by switching cos and sin like it's done in my second function.

I don't know yet if this is mathematical correct implemented when the 2nd planar axis is indeed z and not y.

But at least it's hard to get used to for me (and as it seams to others too ^^)

Hope i managed to explain my point.
  • 0

#19 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 03:21 PM

I missed some functions to determine the distance between two points and the angle the vector between them has.

So I added some functions to my script:

// Function to get the distance between 2 points
function getDistance(point1, point2) {return Math.pow(Math.pow(point1[0] - point2[0], 2) + Math.pow(point1[1] - point2[1], 2), 1/2)};

// Function to get the distance between 2 points given in seperate coordinates
function getDistanceXZ(x1, z1, x2, z2) {return getDistance([x1, z1], [x2, z2])};

// Function to get the direction from one point to another
function getDirection(point1, point2) {return Math.asin((point2[1] - point1[1])/getDistance(point1, point2))};
function getDirectionAlternative(point1, point2) {return Math.acos((point2[0] - point1[0])/getDistance(point1, point2))};

// Function to get the direction from one point to another given in seperate coordinates
function getDirectionXZ(x1, z1, x2, z2) {return getDirection([x1, z1], [x2, z2])};


  • 0

#20 FeXoR

FeXoR

    Centurio

  • Community Members
  • PipPipPipPipPip
  • 862 posts

Posted 29 February 2012 - 03:23 PM

I HOPE with the exchanged sin/cos everything's in order :S
  • 0