diff options
author | kwolekr <kwolekr@minetest.net> | 2016-05-11 03:47:45 -0400 |
---|---|---|
committer | kwolekr <kwolekr@minetest.net> | 2016-05-27 23:23:58 -0400 |
commit | b1eb757e60c155707b8fc1b2497b632246819c7b (patch) | |
tree | 96e9b35b1e0f2b300f379a2703f659130cdab534 /src/dungeongen.cpp | |
parent | 5b05f75a272ede582d7f86d8dbbbf7bc81e81970 (diff) | |
download | minetest-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.
Diffstat (limited to 'src/dungeongen.cpp')
-rw-r--r-- | src/dungeongen.cpp | 29 |
1 files changed, 20 insertions, 9 deletions
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; |