First off, if I suspected an opponent was employing such tactics to cheat, I would resign from such a game. It is simply no fun playing against a cheater.
It seems to me, that what one would like to accomplish is, that after an player as played back a log file (or loaded a save file), that the new player must continue immediately and without interruption, so that the die rolls (and other random numbers) cannot be tampered with.
What that means, is in some sense that the second player (and later) must continue to use the same random number sequence (i.e., the same random number generator seed), or some sequence which comes from a predictable seed. Then, the first player can check, given the seed that was used originally, that the sequence of random numbers used by the second player, is the same or predictable as the one used by the first player.
In practise, this could look like
- Player A starts a game
- A starts a log file - say
A1.vlog- This will put the currently used seed - say
sA1- into the log file
- This will put the currently used seed - say
- A generates random numbers
- Each random number is written to the log file, irrespective of whether it corresponds to a die roll or some other random thing. In this way, the sequence of random numbers is documented in the log file.
- A ends the log file
- A sends the log file to player B
Now it is player Bs turn
- Player B opens the log file
A1.vlog- Vassal will, as part of reading the log file, see the seed -
sA1- written down in step 2 above. - The Random number generator is seeded with that seed
sA1.
- Vassal will, as part of reading the log file, see the seed -
- B starts to step through the log file
A1.vlog- When ever A made a random number, it is read in from the log file. Vassal can now check, that given the above seed -
sA1, that the random number read in is indeed the next random number in the sequence of random numbers - simply by drawing an equivalent random number from the random.- If the random number read from the log file matches the generated random number, then all is good.
- If the random number read from the log file does not match the generated random number, then something is a miss and the problem is reported (an exception is thrown).
- When ever A made a random number, it is read in from the log file. Vassal can now check, that given the above seed -
- Once B has stepped through the log file, B then immediately opens up a new log file - say
B1.vlog.- As above, that means that the current seed should be written to the log.
- However, there’s a bit of a caveat here, as we cannot reuse the old seed -
sA1(otherwise we’d need to know the full sequence of random numbers, which will no be in the newly started log file). - So instead, we draw one random number - say
iB1(along) using the current seed (the one read from the log file) and write that to the log file. - Furthermore, we use that random number as the new seed -
sB1- from the random number generator, and we then write that seed to the log.- While we made a new seed -
sB1, the seed we created is derived from the previous seed -sA1, and therefore we can check, later on, that that seed is as expected. - Had we simply generated a new seed, then we’d be back to the situation where a player may restart logs until favourable outcomes are achieved).
- While we made a new seed -
- However, there’s a bit of a caveat here, as we cannot reuse the old seed -
- As above, that means that the current seed should be written to the log.
- B now generates random numbers and these are written to the log file, just like above.
- B ends the log file -
B1.vlogand sends it to A.
Now comes the part where we check that things are consistent
- A Opens up its own log file
A1.vlogfirst- This reinitialises the Random number generator with the seed in that log file -
sA1.
- This reinitialises the Random number generator with the seed in that log file -
- A then fast-forwards through the log file.
- As above in 7, this will read in the random numbers and check if they are indeed in the sequence (and in order) of the Random number generator given the seed
sA1
- As above in 7, this will read in the random numbers and check if they are indeed in the sequence (and in order) of the Random number generator given the seed
- Once A has stepped through the log file
A1.vlog, the game is back to the state in step 4 above.- But crucially the current random number seed is set to the read seed -
sA1, and we have replayed the sequence of random numbers to the same point as in step 4 above.
- But crucially the current random number seed is set to the read seed -
- A now opens the log sent by B -
B1.vlog- This means that the random number generated in step 8 above -
iB1- using the seedsA1is read in. We can therefore check that that random number is the expected random number - as in step 7 above. - Opening the log also means we read in the seed -
sB1- set in step 8 above, and we seed the Random number generator with that seed.
- This means that the random number generated in step 8 above -
- A nows steps through the log file
B1.vlog- As in step 7 above, every time we see a random number in the log file - generated from the seed
sB1, which we are currently also using, we check if that read random number matches the next random number in the current Random number generator sequence.
- As in step 7 above, every time we see a random number in the log file - generated from the seed
- Once A has stepped through all of the log file
B1.vlog, then A immediately starts a new log file - sayA2.vlog- Again a new random number, given the seed
sB1is generated and written to the log - That random number is set as the new seed -
sA2, and written to the log
- Again a new random number, given the seed
- A does its moves, including generating random numbers from seed
sA2, which are recorded in the log file. - A ends the log file
A2.vlogand sends it to B
Now B follows the same logic:
- B plays back its own log
B1.vlog, so that the seed is set tosB1, and the sequence up to step 10 above is replayed. - B then opens the log file
A2.vlog, which first checks the random number -iA2- based on seedsB1- written in the log, and then reads in the new seedsA2. - B then replayes the log and on each random number checks that it is the next random number in the sequence seeded in
sA2. - B starts a new log -
B2.vlog, generates a random number based onsA2, and sets that as the seed -sB2. - B makes random numbers, based on seed
sB2 - B Closes the log and sends it back to A
In this way, there’s a consistency check on every step, that the sequence of random numbers is ultimate derived from the initial seed - sA1 - possibly via intermittent seeds - sB1, sA2, sB2, sA3, …, which them selves are derived - in a predictable fashion from the first seed sA1. The “trick” is to use the fact that pseudo random number generators are just that - pseudo - and they will always produce the same sequence of random numbers given the same starting point (seed).
The benefit of this approach, in so far as it works and can be implemented in Vassal, is that it is entire self-contained and does not require external services or the like. That also means that reading and writing log files does not require an internet connection.
Note, if no seed is seen in a log file, then no checks are performed. This would be to support older log files. Also note, that the logic carries over to on-line games, as an online game is really just a live replay of a log file. In an online game, all players will use the same seed and they will all see the same sequence of random numbers so they can check for consistency.
Yours,
Christian