diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index 360ddae9c2..f049ccd8c4 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -1282,11 +1282,9 @@ function launchGame() g_GameAttributes.settings.PlayerData[player.player - 1].Name = player.name; } - // This seed is only used for map-generation - if (g_GameAttributes.mapType == "random") - g_GameAttributes.settings.Seed = Math.floor(Math.random() * 65536); - - g_GameAttributes.settings.AISeed = Math.floor(Math.random() * 65536); + // Seed used for both map generation and simulation + g_GameAttributes.settings.Seed = Math.floor(Math.random() * Math.pow(2, 32)); + g_GameAttributes.settings.AISeed = Math.floor(Math.random() * Math.pow(2, 32)); // Used for identifying rated game reports for the lobby g_GameAttributes.matchID = Engine.GetMatchID(); diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index 8c90b9c139..8be12e1025 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -752,6 +752,12 @@ void CSimulation2::SetMapSettings(const std::string& settings) void CSimulation2::SetMapSettings(JS::HandleValue settings) { m->m_MapSettings = settings; + + u32 seed = 0; + if (!m->m_ComponentManager.GetScriptInterface().GetProperty(m->m_MapSettings, "Seed", seed)) + LOGWARNING("CSimulation2::SetInitAttributes: No seed value specified - using %d", seed); + + m->m_ComponentManager.SetRNGSeed(seed); } std::string CSimulation2::GetMapSettingsString() diff --git a/source/simulation2/Simulation2.h b/source/simulation2/Simulation2.h index 5d8c3b0715..ee341b8f8e 100644 --- a/source/simulation2/Simulation2.h +++ b/source/simulation2/Simulation2.h @@ -108,12 +108,14 @@ public: /** * Set the initial map settings (as a UTF-8-encoded JSON string), * which will be used to set up the simulation state. + * Called from atlas. */ void SetMapSettings(const std::string& settings); /** * Set the initial map settings, which will be used * to set up the simulation state. + * Called from MapReader (for all map-types). */ void SetMapSettings(JS::HandleValue settings); diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index a97b16295e..7ea7e2e82a 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2016 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -61,8 +61,6 @@ CComponentManager::CComponentManager(CSimContext& context, shared_ptr (this)); - - // TODO: ought to seed the RNG (in a network-synchronised way) before we use it m_ScriptInterface.ReplaceNondeterministicRNG(m_RNG); m_ScriptInterface.LoadGlobalScripts(); @@ -540,6 +538,11 @@ void CComponentManager::ResetState() m_NextLocalEntityId = FIRST_LOCAL_ENTITY; } +void CComponentManager::SetRNGSeed(u32 seed) +{ + m_RNG.seed(seed); +} + void CComponentManager::RegisterComponentType(InterfaceId iid, ComponentTypeId cid, AllocFunc alloc, DeallocFunc dealloc, const char* name, const std::string& schema) { diff --git a/source/simulation2/system/ComponentManager.h b/source/simulation2/system/ComponentManager.h index aa5981c953..0ab9beb56f 100644 --- a/source/simulation2/system/ComponentManager.h +++ b/source/simulation2/system/ComponentManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2016 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -295,6 +295,11 @@ public: */ void ResetState(); + /** + * Initializes the random number generator with a seed determined by the host. + */ + void SetRNGSeed(u32 seed); + // Various state serialization functions: bool ComputeStateHash(std::string& outHash, bool quick); bool DumpDebugState(std::ostream& stream, bool includeDebugInfo); diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h index ca9e919683..638c33656c 100644 --- a/source/simulation2/tests/test_ComponentManager.h +++ b/source/simulation2/tests/test_ComponentManager.h @@ -96,6 +96,32 @@ public: TS_ASSERT_EQUALS(man.AllocateNewLocalEntity(), (u32)FIRST_LOCAL_ENTITY); } + void test_rng() + { + // Ensure we get the same random number with the same seed + double first; + { + CSimContext context; + CComponentManager man(context, g_ScriptRuntime); + man.SetRNGSeed(123); + + if (!man.m_ScriptInterface.MathRandom(first)) + TS_FAIL("Couldn't get random number!"); + } + + double second; + { + CSimContext context; + CComponentManager man(context, g_ScriptRuntime); + man.SetRNGSeed(123); + + if (!man.m_ScriptInterface.MathRandom(second)) + TS_FAIL("Couldn't get random number!"); + } + + TS_ASSERT_EQUALS(first, second); + } + void test_AddComponent_errors() { CSimContext context;