aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkwolekr <kwolekr@minetest.net>2016-05-11 03:47:45 -0400
committerkwolekr <kwolekr@minetest.net>2016-05-27 23:23:58 -0400
commitb1eb757e60c155707b8fc1b2497b632246819c7b (patch)
tree96e9b35b1e0f2b300f379a2703f659130cdab534
parent5b05f75a272ede582d7f86d8dbbbf7bc81e81970 (diff)
downloadminetest-b1eb757e60c155707b8fc1b2497b632246819c7b.tar.gz
minetest-b1eb757e60c155707b8fc1b2497b632246819c7b.tar.bz2
minetest-b1eb757e60c155707b8fc1b2497b632246819c7b.zip
Fix undefined evaluation order when constructing random vectors
MSVC and GCC evaluate parameters in right-to-left order, whereas Clang evaluates in left-to-right order, and of course, an optimization could leave the order of evaluation completely indeterminate. This commit fixes all instances of the error by explicitly assigning the results of expressions that use PseudoRandom::next() or range() to their respective vector components. The right-to-left evaluation behavior is preserved since Clang is much less commonly used to compile Minetest than GCC and MSVC combined, and would therefore cause the least harm.
-rw-r--r--src/cavegen.cpp67
-rw-r--r--src/dungeongen.cpp29
2 files changed, 47 insertions, 49 deletions
diff --git a/src/cavegen.cpp b/src/cavegen.cpp
index 1beac6f27..5728c1337 100644
--- a/src/cavegen.cpp
+++ b/src/cavegen.cpp
@@ -133,11 +133,9 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y - 1);
// Randomize starting position
- orp = v3f(
- (float)(ps->next() % ar.X) + 0.5,
- (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5,
- (float)(ps->next() % ar.Z) + 0.5
- );
+ orp.Z = (float)(ps->next() % ar.Z) + 0.5;
+ orp.Y = (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5;
+ orp.X = (float)(ps->next() % ar.X) + 0.5;
// Add generation notify begin event
if (gennotify) {
@@ -164,11 +162,10 @@ void CavesRandomWalk::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
void CavesRandomWalk::makeTunnel(bool dirswitch)
{
if (dirswitch && !large_cave) {
- main_direction = v3f(
- ((float)(ps->next() % 20) - (float)10) / 10,
- ((float)(ps->next() % 20) - (float)10) / 30,
- ((float)(ps->next() % 20) - (float)10) / 10
- );
+ main_direction.Z = ((float)(ps->next() % 20) - (float)10) / 10;
+ main_direction.Y = ((float)(ps->next() % 20) - (float)10) / 30;
+ main_direction.X = ((float)(ps->next() % 20) - (float)10) / 10;
+
main_direction *= (float)ps->range(0, 10) / 10;
}
@@ -196,17 +193,13 @@ void CavesRandomWalk::makeTunnel(bool dirswitch)
v3f vec;
// Jump downward sometimes
if (!large_cave && ps->range(0, 12) == 0) {
- vec = v3f(
- (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
- (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
- (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
- );
+ vec.Z = (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2;
+ vec.Y = (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y;
+ vec.X = (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2;
} else {
- vec = v3f(
- (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2,
- (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2,
- (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2
- );
+ vec.Z = (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2;
+ vec.Y = (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2;
+ vec.X = (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2;
}
// Do not make caves that are above ground.
@@ -446,11 +439,9 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y - 1);
// Randomize starting position
- orp = v3f(
- (float)(ps->next() % ar.X) + 0.5,
- (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5,
- (float)(ps->next() % ar.Z) + 0.5
- );
+ orp.Z = (float)(ps->next() % ar.Z) + 0.5;
+ orp.Y = (float)(ps->range(route_start_y_min, route_start_y_max)) + 0.5;
+ orp.X = (float)(ps->next() % ar.X) + 0.5;
// Add generation notify begin event
if (gennotify != NULL) {
@@ -477,11 +468,10 @@ void CavesV6::makeCave(MMVManip *vm, v3s16 nmin, v3s16 nmax,
void CavesV6::makeTunnel(bool dirswitch)
{
if (dirswitch && !large_cave) {
- main_direction = v3f(
- ((float)(ps->next() % 20) - (float)10) / 10,
- ((float)(ps->next() % 20) - (float)10) / 30,
- ((float)(ps->next() % 20) - (float)10) / 10
- );
+ main_direction.Z = ((float)(ps->next() % 20) - (float)10) / 10;
+ main_direction.Y = ((float)(ps->next() % 20) - (float)10) / 30;
+ main_direction.X = ((float)(ps->next() % 20) - (float)10) / 10;
+
main_direction *= (float)ps->range(0, 10) / 10;
}
@@ -506,19 +496,16 @@ void CavesV6::makeTunnel(bool dirswitch)
);
}
- v3f vec(
- (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
- (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2,
- (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
- );
+ v3f vec;
+ vec.Z = (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2;
+ vec.Y = (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2;
+ vec.X = (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2;
// Jump downward sometimes
if (!large_cave && ps->range(0, 12) == 0) {
- vec = v3f(
- (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2,
- (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y,
- (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2
- );
+ vec.Z = (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2;
+ vec.Y = (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y;
+ vec.X = (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2;
}
// Do not make caves that are entirely above ground, to fix shadow bugs
diff --git a/src/dungeongen.cpp b/src/dungeongen.cpp
index 5bfc320c9..f7f9b8b50 100644
--- a/src/dungeongen.cpp
+++ b/src/dungeongen.cpp
@@ -135,17 +135,23 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
bool fits = false;
for (u32 i = 0; i < 100 && !fits; i++) {
bool is_large_room = ((random.next() & 3) == 1);
- roomsize = is_large_room ?
- v3s16(random.range(8, 16), random.range(8, 16), random.range(8, 16)) :
- v3s16(random.range(4, 8), random.range(4, 6), random.range(4, 8));
+ if (is_large_room) {
+ roomsize.Z = random.range(8, 16);
+ roomsize.Y = random.range(8, 16);
+ roomsize.X = random.range(8, 16);
+ } else {
+ roomsize.Z = random.range(4, 8);
+ roomsize.Y = random.range(4, 6);
+ roomsize.X = random.range(4, 8);
+ }
roomsize += dp.roomsize;
// start_padding is used to disallow starting the generation of
// a dungeon in a neighboring generation chunk
- roomplace = vm->m_area.MinEdge + start_padding + v3s16(
- random.range(0, areasize.X - roomsize.X - start_padding.X),
- random.range(0, areasize.Y - roomsize.Y - start_padding.Y),
- random.range(0, areasize.Z - roomsize.Z - start_padding.Z));
+ roomplace = vm->m_area.MinEdge + start_padding;
+ roomplace.Z += random.range(0, areasize.Z - roomsize.Z - start_padding.Z);
+ roomplace.Y += random.range(0, areasize.Y - roomsize.Y - start_padding.Y);
+ roomplace.X += random.range(0, areasize.X - roomsize.X - start_padding.X);
/*
Check that we're not putting the room to an unknown place,
@@ -227,7 +233,9 @@ void DungeonGen::makeDungeon(v3s16 start_padding)
makeCorridor(doorplace, doordir, corridor_end, corridor_end_dir);
// Find a place for a random sized room
- roomsize = v3s16(random.range(4, 8), random.range(4, 6), random.range(4, 8));
+ roomsize.Z = random.range(4, 8);
+ roomsize.Y = random.range(4, 6);
+ roomsize.X = random.range(4, 8);
roomsize += dp.roomsize;
m_pos = corridor_end;
@@ -587,7 +595,10 @@ v3s16 rand_ortho_dir(PseudoRandom &random, bool diagonal_dirs)
do {
trycount++;
- dir = v3s16(random.next() % 3 - 1, 0, random.next() % 3 - 1);
+
+ dir.Z = random.next() % 3 - 1;
+ dir.Y = 0;
+ dir.X = random.next() % 3 - 1;
} while ((dir.X == 0 && dir.Z == 0) && trycount < 10);
return dir;