Add ensureDeterminism to saves

This commit is contained in:
Tamás Bálint Misius 2023-04-15 19:01:42 +02:00
parent 9c3b966c18
commit a8604ef579
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
10 changed files with 64 additions and 50 deletions

View File

@ -539,6 +539,7 @@ void GameSave::readOPS(const std::vector<char> &data)
CheckBsonFieldFloat(iter, "ambientAirTemp", &ambientAirTemp);
CheckBsonFieldInt(iter, "edgeMode", &edgeMode);
CheckBsonFieldInt(iter, "pmapbits", &pmapbits);
CheckBsonFieldBool(iter, "ensureDeterminism", &ensureDeterminism);
CheckBsonFieldLong(iter, "frameCount", reinterpret_cast<int64_t *>(&frameCount));
CheckBsonFieldLong(iter, "rngState0", reinterpret_cast<int64_t *>(&rngState[0]));
CheckBsonFieldLong(iter, "rngState1", reinterpret_cast<int64_t *>(&rngState[1]));
@ -2546,6 +2547,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
bson_append_binary(&b, "soapLinks", (char)BSON_BIN_USER, (const char *)&soapLinkData[0], soapLinkDataLen);
if (ensureDeterminism)
{
bson_append_bool(&b, "ensureDeterminism", ensureDeterminism);
bson_append_binary(&b, "blockAir", (char)BSON_BIN_USER, (const char *)&blockAirData[0], blockAirDataLen);
bson_append_long(&b, "frameCount", int64_t(frameCount));
bson_append_long(&b, "rngState0", int64_t(rngState[0]));

View File

@ -1,6 +1,7 @@
#pragma once
#include "common/Plane.h"
#include "common/String.h"
#include "common/tpt-rand.h"
#include "simulation/Sign.h"
#include "simulation/Particle.h"
#include "Misc.h"
@ -95,8 +96,8 @@ public:
bool hasPressure = false;
bool hasAmbientHeat = false;
bool hasBlockAirMaps = false; // only written by readOPS, never read
bool ensureDeterminism = false; // only read by serializeOPS, never written
std::array<uint64_t, 2> rngState;
bool ensureDeterminism = false; // only taken seriously by serializeOPS; readOPS may set this even if the save does not have everything required for determinism
RNG::State rngState;
uint64_t frameCount = 0;
//Simulation data

View File

@ -5,8 +5,11 @@
class RNG
{
public:
using State = std::array<uint64_t, 2>;
private:
std::array<uint64_t, 2> s;
State s;
uint64_t next();
public:
unsigned int operator()();
@ -18,12 +21,12 @@ public:
RNG();
void seed(unsigned int sd);
void state(std::array<uint64_t, 2> ns)
void state(State ns)
{
s = ns;
}
std::array<uint64_t, 2> state() const
State state() const
{
return s;
}

View File

@ -934,6 +934,31 @@ SaveInfo * GameModel::GetSave()
return currentSave;
}
void GameModel::SaveToSimParameters(const GameSave *saveData)
{
SetPaused(saveData->paused | GetPaused());
sim->gravityMode = saveData->gravityMode;
sim->customGravityX = saveData->customGravityX;
sim->customGravityY = saveData->customGravityY;
sim->air->airMode = saveData->airMode;
sim->air->ambientAirTemp = saveData->ambientAirTemp;
sim->edgeMode = saveData->edgeMode;
sim->legacy_enable = saveData->legacyEnable;
sim->water_equal_test = saveData->waterEEnabled;
sim->aheat_enable = saveData->aheatEnable;
if (saveData->gravityEnable && !sim->grav->IsEnabled())
{
sim->grav->start_grav_async();
}
else if (!saveData->gravityEnable && sim->grav->IsEnabled())
{
sim->grav->stop_grav_async();
}
sim->frameCount = saveData->frameCount;
sim->rng.state(saveData->rngState);
sim->ensureDeterminism = saveData->ensureDeterminism;
}
void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
{
if(currentSave != newSave)
@ -947,23 +972,10 @@ void GameModel::SetSave(SaveInfo * newSave, bool invertIncludePressure)
delete currentFile;
currentFile = NULL;
if(currentSave && currentSave->GetGameSave())
if (newSave && newSave->GetGameSave())
{
GameSave * saveData = currentSave->GetGameSave();
SetPaused(saveData->paused | GetPaused());
sim->gravityMode = saveData->gravityMode;
sim->customGravityX = saveData->customGravityX;
sim->customGravityY = saveData->customGravityY;
sim->air->airMode = saveData->airMode;
sim->air->ambientAirTemp = saveData->ambientAirTemp;
sim->edgeMode = saveData->edgeMode;
sim->legacy_enable = saveData->legacyEnable;
sim->water_equal_test = saveData->waterEEnabled;
sim->aheat_enable = saveData->aheatEnable;
if(saveData->gravityEnable)
sim->grav->start_grav_async();
else
sim->grav->stop_grav_async();
GameSave *saveData = newSave->GetGameSave();
SaveToSimParameters(saveData);
sim->clear_sim();
ren->ClearAccumulation();
if (!sim->Load(saveData, !invertIncludePressure))
@ -1011,27 +1023,10 @@ void GameModel::SetSaveFile(SaveFile * newSave, bool invertIncludePressure)
delete currentSave;
currentSave = NULL;
if(newSave && newSave->GetGameSave())
if (newSave && newSave->GetGameSave())
{
GameSave * saveData = newSave->GetGameSave();
SetPaused(saveData->paused | GetPaused());
sim->gravityMode = saveData->gravityMode;
sim->customGravityX = saveData->customGravityX;
sim->customGravityY = saveData->customGravityY;
sim->air->airMode = saveData->airMode;
sim->air->ambientAirTemp = saveData->ambientAirTemp;
sim->edgeMode = saveData->edgeMode;
sim->legacy_enable = saveData->legacyEnable;
sim->water_equal_test = saveData->waterEEnabled;
sim->aheat_enable = saveData->aheatEnable;
if(saveData->gravityEnable && !sim->grav->IsEnabled())
{
sim->grav->start_grav_async();
}
else if(!saveData->gravityEnable && sim->grav->IsEnabled())
{
sim->grav->stop_grav_async();
}
GameSave *saveData = newSave->GetGameSave();
SaveToSimParameters(saveData);
sim->clear_sim();
ren->ClearAccumulation();
if (!sim->Load(saveData, !invertIncludePressure))

View File

@ -114,6 +114,9 @@ private:
void notifyToolTipChanged();
void notifyQuickOptionsChanged();
void notifyLastToolChanged();
void SaveToSimParameters(const GameSave *saveData);
public:
GameModel();
~GameModel();

View File

@ -214,6 +214,17 @@ static int simHash(lua_State *l)
return 1;
}
static int simEnsureDeterminism(lua_State *l)
{
if (lua_gettop(l))
{
luacon_sim->ensureDeterminism = lua_toboolean(l, 1);
return 0;
}
lua_pushboolean(l, luacon_sim->ensureDeterminism);
return 1;
}
LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
TPTScriptInterface(c, m),
luacon_mousex(0),
@ -1003,6 +1014,7 @@ void LuaScriptInterface::initSimulationAPI()
{"temperatureScale", simulation_temperatureScale},
{"randomseed", simRandomseed},
{"hash", simHash},
{"ensureDeterminism", simEnsureDeterminism},
{NULL, NULL}
};
luaL_register(l, "simulation", simulationAPIMethods);

View File

@ -64,8 +64,6 @@ int Simulation::Load(const GameSave * originalSave, bool includePressure, int fu
}
RecalcFreeParticles(false);
frameCount = save->frameCount;
rng.state(save->rngState);
auto &possiblyCarriesType = Particle::PossiblyCarriesType();
auto &properties = Particle::GetProperties();
@ -490,15 +488,12 @@ GameSave * Simulation::Save(bool includePressure, int fullX, int fullY, int full
}
}
}
if (includePressure)
if (includePressure || ensureDeterminism)
{
newSave->hasPressure = true;
newSave->hasAmbientHeat = true;
}
if (true) // TODO: tie to an option maybe?
{
newSave->ensureDeterminism = true;
}
newSave->ensureDeterminism = ensureDeterminism;
newSave->stkm.rocketBoots1 = player.rocketBoots;
newSave->stkm.rocketBoots2 = player2.rocketBoots;
@ -1092,6 +1087,7 @@ int Simulation::parts_avg(int ci, int ni,int t)
void Simulation::clear_sim(void)
{
ensureDeterminism = false;
frameCount = 0;
debug_nextToUpdate = 0;
debug_mostRecentlyUpdated = -1;

View File

@ -119,6 +119,7 @@ public:
int sandcolour_frame;
int deco_space;
uint64_t frameCount;
bool ensureDeterminism;
int Load(const GameSave * save, bool includePressure);
int Load(const GameSave * save, bool includePressure, int x, int y);

View File

@ -2,6 +2,7 @@
#include "Particle.h"
#include "Sign.h"
#include "Stickman.h"
#include "common/tpt-rand.h"
#include <vector>
#include <array>
#include <json/json.h>
@ -36,7 +37,7 @@ public:
std::vector<sign> signs;
uint64_t FrameCount;
std::array<uint64_t, 2> RngState;
RNG::State RngState;
uint32_t Hash() const;

View File

@ -68,7 +68,7 @@ struct SnapshotDelta
HunkVector<uint32_t> stickmen;
SingleDiff<std::vector<sign>> signs;
SingleDiff<uint64_t> FrameCount;
SingleDiff<std::array<uint64_t, 2>> RngState;
SingleDiff<RNG::State> RngState;
SingleDiff<Json::Value> Authors;