Opened 7 years ago

Closed 6 years ago

#4600 closed defect (fixed)

Berries inside mines

Reported by: elexis Owned by: elexis
Priority: Should Have Milestone: Alpha 23
Component: Maps Keywords:
Cc: Patch:

Description (last modified by elexis)

A classic bug of 0AD. The initial resources are just placed randomly at a fixed distance to the CC, thus initial resources can collide.

The correct way to fix this would be to add a retry loop and unify the berry placement in all maps.

This is an example reported by cc: https://trac.wildfiregames.com/raw-attachment/ticket/4600/kerala.jpg

Attachments (4)

kerala.jpg (548.0 KB ) - added by elexis 7 years ago.
commands_kerala.txt (8.3 KB ) - added by elexis 7 years ago.
screenshot0772.jpg (552.1 KB ) - added by elexis 7 years ago.
commands.txt (2.0 KB ) - added by elexis 6 years ago.
Forest inside metal mine near my CC on lions den with alpha 22 vanilla and/or mod

Download all attachments as: .zip

Change History (18)

by elexis, 7 years ago

Attachment: kerala.jpg added

by elexis, 7 years ago

Attachment: commands_kerala.txt added

comment:1 by elexis, 7 years ago

Description: modified (diff)

comment:2 by temple, 7 years ago

The problem is here:

// create berry bushes
var bbAngle = randFloat(0, TWO_PI);

// create metal mine
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3)
	mAngle = randFloat(0, TWO_PI);

// create stone mines
mAngle += randFloat(PI/8, PI/4);

If one angle is close to 2*pi and the other close to 0, then they'll quit the while loop even though the angles are close to each other (because they wrap around). Here's a picture of berries overlapping with stone on tiny mainland with eight players, seed = 4393. Berries are at 13 degrees, metal's at 341 degrees (a difference of 32 degrees < 60 degrees = pi/3), and stone's at 368 = 8 degrees.

http://i.imgur.com/wX7HUlN.png

Here's my suggestion:

var bbAngle = randFloat(0, TWO_PI);
var mAngle = bbAngle + randFloat(PI/4, 3*PI/2);
var sAngle = mAngle + PI/4;

This will ensure that there's at least a pi/4 separation between the berries and each mine.

(There is some randomness when placing the objects because of the max radius in SimpleObject: 3 for berries, 0 for metal, 2 for stone. With a bbDist = 12 tile radius, pi/4 is 9 tiles. Mines have a 20m = 5 tile diameter footprint, so we could also use a 2 tile max radius for metal without running into problems with overlapping mines.)

Elexis has been nicely cleaning up the random map files so I'm just offering this comment rather than stepping on his toes. :)

by elexis, 7 years ago

Attachment: screenshot0772.jpg added

comment:3 by elexis, 7 years ago

That issue occurs or occured on most maps. For many maps we have chosen the same approach you have proposed here - increasing the angle. But it's even nicer to completely randomize the angle and do retry loops as in r17909. The result will be that the starting resources won't be compartmentalized like an instant-meal in always the same order, but they can be close to each other while just avoiding collisions.

https://trac.wildfiregames.com/raw-attachment/ticket/4600/screenshot0772.jpg

Had seen a variant where those trees formed a perfect half-circle around the mine, was really beautiful.

(Since that bug is contained in every copy of the buggy code, tickets like these will only go away if all rmgen duplication is nuked.)

in reply to:  2 ; comment:4 by mimo, 7 years ago

Replying to temple:

The problem is here:

// create berry bushes
var bbAngle = randFloat(0, TWO_PI);

// create metal mine
var mAngle = bbAngle;
while(abs(mAngle - bbAngle) < PI/3)
	mAngle = randFloat(0, TWO_PI);

// create stone mines
mAngle += randFloat(PI/8, PI/4);

If one angle is close to 2*pi and the other close to 0, then they'll quit the while loop even though the angles are close to each other (because they wrap around). Here's a picture of berries overlapping with stone on tiny mainland with eight players, seed = 4393. Berries are at 13 degrees, metal's at 341 degrees (a difference of 32 degrees < 60 degrees = pi/3), and stone's at 368 = 8 degrees.

For this problem of near equality modulo 2*PI, the best solution would be

 // create metal mine
 var mAngle = bbAngle;
 while(abs(mAngle - bbAngle) < PI/3)
 	mAngle = randFloat(bbAngle - PI, bbAngle + PI);

in reply to:  4 ; comment:5 by temple, 7 years ago

Replying to elexis:

For many maps we have chosen the same approach you have proposed here - increasing the angle.

Well, I actually decreased the angle from pi/3 to pi/4. I kept the metal and stone mines near each other because players are used to making one storehouse for both, and they couldn't do that if the mines were placed on opposite sides of the cc. But I usually make more than one storehouse anyway so for me it's fine.

But it's even nicer to completely randomize the angle and do retry loops as in r17909.

I'll agree with this as long as you're okay with the storehouse thing.

Replying to mimo:

For this problem of near equality modulo 2*PI, the best solution would be

 // create metal mine
 var mAngle = bbAngle;
 while(abs(mAngle - bbAngle) < PI/3)
 	mAngle = randFloat(bbAngle - PI, bbAngle + PI);

This won't work because the stone mine angle is gotten by adding to the metal mine angle.

mAngle += randFloat(PI/8, PI/4);

That is, the berries and stone could be within pi/3 - pi/4 = 15 degrees of each other, which is enough room for overlap.

That's why I did:

var mAngle = bbAngle + randFloat(PI/4, 3*PI/2);

rather than:

var mAngle = bbAngle + randFloat(PI/4, 7*PI/4);

comment:6 by elexis, 7 years ago

players are used to making one storehouse for both

Players should adapt to the map, not the other way around IMO

(More relevant to me would be that initial mines aren't exposed to the near enemy. Sometimes an enemy can build a tower near his CC and deny the initial metal mines, defeating a player by investing like 300 resources. Also mines extremely overlapping with the "stronghold" player placement sometimes.)

in reply to:  5 comment:7 by mimo, 7 years ago

Replying to temple:

Replying to mimo:

For this problem of near equality modulo 2*PI, the best solution would be

 // create metal mine
 var mAngle = bbAngle;
 while(abs(mAngle - bbAngle) < PI/3)
 	mAngle = randFloat(bbAngle - PI, bbAngle + PI);

This won't work because the stone mine angle is gotten by adding to the metal mine angle.

My previous comment was given as an example of how to avoid a collision with two sources (as you quoted in your own messages). If now the problem is with three sources, an easy generalization is:

If bbAngle is first chosen, and you want two angles m1Angle and m2Angle with all separated by at least Delta, you can just do

m1Angle = 0;
m2Angle = 0;
while (abs(m1Angle - m2Angle) < Delta)
{
	m1Angle = randFloat(-PI + Delta, PI - Delta);
	m2Angle = randFloat(-PI + Delta, PI - Delta);
}
m1Angle = m1Angle + bbAngle + PI;
m2Angle = m2Angle + bbAngle + PI;

And if you want in addition to have both mines not farther than Alpha (which i agree with elexis we should not do here, but can be useful for other purposes), you change

m2Angle = randFloat(-PI + Delta, PI - Delta);

by

m2Angle = randFloat(Math.max(-PI + Delta, m1Angle - Alpha), Math.min(PI - Delta, m1Angle + Alpha));

comment:8 by temple, 7 years ago

Players should adapt to the map, not the other way around IMO

That's fine, I'm just pointing out that some players will have to make two storehouses while others only need one. Not a huge deal considering that the resources outside the initial ones are placed randomly rather than fairly.

My previous comment was given as an example of how to avoid a collision with two sources (as you quoted in your own messages).

Okay.

I'll point out another thing, that constraints don't take into account footprints, so in the avoidClasses of elexis's retry loop we might want to group berries and mines separately, and be careful about the max radius in the SimpleObject.

(More relevant to me would be that initial mines aren't exposed to the near enemy. Sometimes an enemy can build a tower near his CC and deny the initial metal mines, defeating a player by investing like 300 resources. Also mines extremely overlapping with the "stronghold" player placement sometimes.)

I did a pizza game on Empire (stronghold) some weeks ago and I think resources were even inside the cc's. (I think the cc's were overlapping too.)

by elexis, 6 years ago

Attachment: commands.txt added

Forest inside metal mine near my CC on lions den with alpha 22 vanilla and/or mod

comment:9 by elexis, 6 years ago

In 20290:

Fix collisions of random forests and mines with starting resources on Cycladic Archipelago and the Lion's Den. Refs #4600.

comment:10 by elexis, 6 years ago

In 20316:

Fix collisions of random resources and starting base resources on the Corinthian Isthmus random map script, refs #4600.

comment:11 by elexis, 6 years ago

stronghold, resources were even inside the cc

The trve way to do stronghold base placement is present in Island Stronghold. It places the resources at a smart angle that avoids the neighbors bases. With the tileclass checks (clPlayer and clBaseResource) and retry loops alone the impact of the problem is reduced. Only that a civic center is placed into a resource sometimes. That rmgen2 stronghold placement needs to be rewritten to account for that.

constraints don't take into account footprints

A 4 tile distance in avoidClasses fits for all resources. Currently. Requiring that hardcoded number in every random map script. So every map could should might have to be reworked with a footprint check mechanism by swim.

comment:12 by elexis, 6 years ago

temple reported in Phab:rP20405 that many createStragglerTrees calls miss a constraint check for clFood (for berries).

The createFood calls should be confirmed to test against clMetal and clRock where needed.

comment:13 by elexis, 6 years ago

Milestone: BacklogAlpha 23

Closing as fixed since almost the entire discussion is about the starting resources.

comment:14 by elexis, 6 years ago

Owner: set to elexis
Resolution: fixed
Status: newclosed

In 20815:

Implement random map script playerbase function.
Unifies 54 variants of the rmgen playerbase code, fixes #4805.

Add retry loops to prevent collisions of starting resources, fixes #4600 and
resources placed outside of the map area, fixes #4796.

Lays the foundation to test for collisions with Iberian walls, refs #2192 and
allows to rearrange the starting resources on all random maps without being confronted with code.

Delete remains of misc.js, leaving the rmgen files sorted by logic, fixes #4804.
Concludes what was started in rP18816, rP19282, specifically the 82 rmgen commits starting rP20115, rP20301.
Uses vector algebra, refs #4845.
Removes many Math proxy calls, refs #4933.
Removes 35 unused elevation and 24 unused cliffRadius variables, demonstrating the copy&paste antipattern.
Reduce iberian-wall hardcoding to one line, refs #4940.

Note: See TracTickets for help on using tickets.