fix(skirmish): Improve determinism for restarted games by resetting slot values#2373
fix(skirmish): Improve determinism for restarted games by resetting slot values#2373Caball009 wants to merge 9 commits intoTheSuperHackers:mainfrom
Conversation
…andomized slot values.
|
| Filename | Overview |
|---|---|
| Core/GameEngine/Include/GameNetwork/GameInfo.h | Adds m_saveOffOriginalInfo Bool member and changes saveOffOriginalInfo() return type from void to Bool; clean, well-placed change. |
| Core/GameEngine/Source/GameNetwork/GameInfo.cpp | Implements the Bool guard in saveOffOriginalInfo() and resets the flag in setState() (non-player branch) and reset(); one subtle concern that SLOT_PLAYER path already resets via reset() but the non-player branch now also resets, covering AI/open/closed slots between games correctly. |
| GeneralsMD/Code/GameEngine/Include/GameLogic/GameLogic.h | Adds free-function declaration const char* toString(GameMode mode) used for the new debug assert message. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp | Adds toString(GameMode) helper, calls saveOffOriginalInfo() and uses its Bool return to conditionally restore original slot values on restart; DEBUG_ASSERTCRASH guards against unexpected non-skirmish restarts but the restore logic executes unconditionally in release builds. |
Sequence Diagram
sequenceDiagram
participant UI as Game Lobby
participant GS as GameSlot
participant GL as GameLogic
Note over UI,GL: First game start
UI->>GS: setState(SLOT_EASY_AI / SLOT_PLAYER)
GS->>GS: reset() → m_saveOffOriginalInfo = TRUE
GL->>GS: startNewGame() → saveOffOriginalInfo()
GS->>GS: save color/startPos/playerTemplate → orig*
GS->>GS: m_saveOffOriginalInfo = FALSE
GS-->>GL: returns TRUE
GL->>GL: populateRandomSideAndColor() (consumes logical seed)
Note over UI,GL: Restarted game (no lobby, m_saveOffOriginalInfo stays FALSE)
GL->>GS: startNewGame() → saveOffOriginalInfo()
GS-->>GL: returns FALSE (already saved)
GL->>GS: setColor(getOriginalColor())
GL->>GS: setStartPos(getOriginalStartPos())
GL->>GS: setPlayerTemplate(getOriginalPlayerTemplate())
GL->>GL: populateRandomSideAndColor() (same seed → same values)
Note over UI,GL: If lobby is visited between games
UI->>GS: setState(SLOT_EASY_AI / SLOT_PLAYER)
GS->>GS: m_saveOffOriginalInfo = TRUE (reset)
GL->>GS: startNewGame() → saveOffOriginalInfo()
GS-->>GL: returns TRUE (fresh save)
Reviews (3): Last reviewed commit: "Set 'm_saveOffOriginalInfo' back to true..." | Re-trigger Greptile
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
xezon
left a comment
There was a problem hiding this comment.
Greptile is still complaining about something?
So that the original player data is saved properly for AI players.
Yes, that was a good point. I think it could have affected the randomization of AI players if a game was loaded from inside another game or replay. GeneralsGameCode/Core/GameEngine/Source/GameNetwork/GameInfo.cpp Lines 1594 to 1600 in 637dbba It should work correctly now because Replication in Generals still needs doing. |
| } | ||
| else | ||
| { | ||
| m_saveOffOriginalInfo = TRUE; |
There was a problem hiding this comment.
The reason for this is unintuitive.
Perhaps it would be better to have 2 versions of saveOffOriginalInfo, one used in the xfer and the other on new game start? Or just test the boolean outside of saveOffOriginalInfo.
That may also be a good opportunity to fix the name of saveOffOriginalInfo, for example saveOriginalSetup.
Restarted skirmish games may not start with the same logical seed value as the first start. This depends on whether there are players with a random color / position / faction. Those random values are determined by using and updating the logical seed on the first start, after which the random values are stored. That means that for restarted games the logical seed isn't used or updated for those purposes. This PR resets those values to improve determinism for restarted games.
You can put a breakpoint after
GameLogic::startNewGameand compare the values oftheGameLogicSeedfor the first start and following starts and see how the values for the first start deviate from restarts.TODO: