Page 1 of 1
[1.1.72] rounding error with create_entity{position}
Posted: Thu Nov 17, 2022 10:57 pm
by BurninSun
When calling `create_entity`, negative positions are rounded differently than positive positions. Any negative fraction less than 1/256 is rounded but positive numbers are just truncated.
Examples creating assembly machines:
`/c game.player.surface.create_entity({name="assembling-machine-1", position={x=0, y=10}})` centered at y=10.5 <-- expected
`/c game.player.surface.create_entity({name="assembling-machine-1", position={x=0, y=9.99999999}})` centered at y=9.5 <-- expected
`/c game.player.surface.create_entity({name="assembling-machine-1", position={x=0, y=-10.00390625}})` centered at y=10.5 <-- expected
`/c game.player.surface.create_entity({name="assembling-machine-1", position={x=0, y=-10.00390624}})` centered at y=9.5 <-- NOT expected
This produces the following mappings:
[2,3) --> 2.5
[1,2) --> 1.5
(-1/256, 1) --> 0.5 <-- unexpected mapping range
(-1-1/256, -1/256] --> -0.5
(-2-1/256, -1-1/256] --> -1.5
(-3-1/256, -2-1/256] --> -2.5
Re: [1.1.72] rounding error with create_entity{position}
Posted: Fri Nov 18, 2022 5:36 am
by boskid
This topic is not as simple to call it a bug based on what you are describing. It is simillar to
97568 because there are actually 2 layers of rounding: first layer of rounding happens when values from lua are converted to MapPosition (where coordinates are fixed points with resolution of 1/256th) and second layer is buildPosition rounding which uses provided MapPosition values. It is not possible to have the entity's build position function take a raw position with doubles to perform rounding in one step due to all layers of abstraction that are between lua and entity creation.
Most reasonable approach for me would be to tweak the MapPosition rounding in a way that the exact values are in the middle of the range that rounds to such values, but that would mean [-1/512, 1/512) would round to 0, [1/512, 3/512) would round to 1/256 for the MapPosition, and when looking at both rounding at once (MapPosition and build position function), it would look like positions from [-1/512, 1-1/512) would consistently give you the entity position of 0.5 (regardless if it would be x or y coordinate) for entities of odd tile grid size.
Re: [1.1.72] rounding error with create_entity{position}
Posted: Fri Nov 18, 2022 6:20 am
by BurninSun
I don't really have a good solution. For symmetry, it would be best to round MapPosition towards 0 then split the tile giving a mapping
[1,2) -> 1.5
[0,1) -> 0.5
(-1, 0) -> -0.5
(-2, -1] -> -1.5
But that means iterating across 0 (eg, -2, -1, 0, 1, 2) would skip the mapping to -0.5. If instead the MapPosition was simply floored
[1,2) -> 1.5
[0,1) -> 0.5
[-1, 0) -> -0.5
[-2, -1) -> -1.5
Would mean someone setting a specific position of -2 would end up at -1.5 which seems odd as well.
Not sure what the best approach is.
Re: [1.1.72] rounding error with create_entity{position}
Posted: Fri Nov 18, 2022 9:33 am
by boskid
I am going to move this to Duplicates due to
97568 but it could also go to Not a bug (because there is no explicit guarantee that rounding of coordinates for MapPosition and build position function are equal) or Wont fix (because changes here have a really high possibility of being breaking changes which i cannot accept anymore in 1.1.x branch). Description specifies the problem as if there was only one rounding and there is cascade of 2 roundings which are independent of each other. It would be nice if you would stop using coordinates that are not multiple of 1/256th so you would not notice the first rounding, or you could use x+0.5 when iterating over integer coordinates to make sure the build position function would not be working on the threshold and deciding in the direction that does not match your expectation because of first rounding. There is always a rage quit solution i can implement, first would be to make MapPosition parsing from lua to throw an error if coordinate is not a multiple of 1/256th, second would be to abort entity creation if the given position is not at the correct build position. Both are harmful but if modders have problems with soft requirements being too soft then there will be hard requirements everywhere.