Commit 1c829da0 authored by salix5's avatar salix5 Committed by GitHub

update RNG and uniform distribution, part 1 (#2362)

Old version:
pheader.flag does not contain REPLAY_UNIFORM
RNG: mt19937
distribution: almost-uniform

New version
pheader.flag contains REPLAY_UNIFORM
RNG: mt19937
distribution: uniform

* add bounds checking

* update RNG in replay mode

* replace mtrandom with mt19937

* replace mtrandom with mt19937
parent 2c9a0eee
...@@ -29,7 +29,7 @@ int DuelClient::last_select_hint = 0; ...@@ -29,7 +29,7 @@ int DuelClient::last_select_hint = 0;
char DuelClient::last_successful_msg[0x2000]; char DuelClient::last_successful_msg[0x2000];
unsigned int DuelClient::last_successful_msg_length = 0; unsigned int DuelClient::last_successful_msg_length = 0;
wchar_t DuelClient::event_string[256]; wchar_t DuelClient::event_string[256];
mtrandom DuelClient::rnd; mt19937 DuelClient::rnd;
bool DuelClient::is_refreshing = false; bool DuelClient::is_refreshing = false;
int DuelClient::match_kill = 0; int DuelClient::match_kill = 0;
...@@ -58,7 +58,7 @@ bool DuelClient::StartClient(unsigned int ip, unsigned short port, bool create_g ...@@ -58,7 +58,7 @@ bool DuelClient::StartClient(unsigned int ip, unsigned short port, bool create_g
return false; return false;
} }
connect_state = 0x1; connect_state = 0x1;
rnd.reset(time(0)); rnd.reset((unsigned int)time(nullptr));
if(!create_game) { if(!create_game) {
timeval timeout = {5, 0}; timeval timeout = {5, 0};
event* resp_event = event_new(client_base, 0, EV_TIMEOUT, ConnectTimeout, 0); event* resp_event = event_new(client_base, 0, EV_TIMEOUT, ConnectTimeout, 0);
...@@ -681,7 +681,12 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) { ...@@ -681,7 +681,12 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
char* prep = pdata; char* prep = pdata;
Replay new_replay; Replay new_replay;
memcpy(&new_replay.pheader, prep, sizeof(ReplayHeader)); memcpy(&new_replay.pheader, prep, sizeof(ReplayHeader));
time_t starttime = new_replay.pheader.seed; time_t starttime;
if (new_replay.pheader.flag & REPLAY_UNIFORM)
starttime = new_replay.pheader.start_time;
else
starttime = new_replay.pheader.seed;
tm* localedtime = localtime(&starttime); tm* localedtime = localtime(&starttime);
wchar_t timetext[40]; wchar_t timetext[40];
wcsftime(timetext, 40, L"%Y-%m-%d %H-%M-%S", localedtime); wcsftime(timetext, 40, L"%Y-%m-%d %H-%M-%S", localedtime);
...@@ -1651,7 +1656,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1651,7 +1656,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
SetResponseI(-1); SetResponseI(-1);
mainGame->dField.ClearChainSelect(); mainGame->dField.ClearChainSelect();
if(mainGame->chkWaitChain->isChecked() && !mainGame->ignore_chain) { if(mainGame->chkWaitChain->isChecked() && !mainGame->ignore_chain) {
mainGame->WaitFrameSignal(rnd.real() * 20 + 20); mainGame->WaitFrameSignal(rnd.get_random_integer(20, 40));
} }
DuelClient::SendResponse(); DuelClient::SendResponse();
return true; return true;
...@@ -1751,7 +1756,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) { ...@@ -1751,7 +1756,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(!pzone) { if(!pzone) {
if(mainGame->chkRandomPos->isChecked()) { if(mainGame->chkRandomPos->isChecked()) {
do { do {
respbuf[2] = rnd.real() * 7; respbuf[2] = rnd.get_random_integer(0, 6);
} while(!(filter & (1 << respbuf[2]))); } while(!(filter & (1 << respbuf[2])));
} else { } else {
if (filter & 0x40) respbuf[2] = 6; if (filter & 0x40) respbuf[2] = 6;
......
...@@ -36,7 +36,7 @@ private: ...@@ -36,7 +36,7 @@ private:
static char last_successful_msg[0x2000]; static char last_successful_msg[0x2000];
static unsigned int last_successful_msg_length; static unsigned int last_successful_msg_length;
static wchar_t event_string[256]; static wchar_t event_string[256];
static mtrandom rnd; static mt19937 rnd;
public: public:
static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true); static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true);
static void ConnectTimeout(evutil_socket_t fd, short events, void* arg); static void ConnectTimeout(evutil_socket_t fd, short events, void* arg);
......
...@@ -465,7 +465,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) { ...@@ -465,7 +465,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break; break;
wchar_t infobuf[256]; wchar_t infobuf[256];
std::wstring repinfo; std::wstring repinfo;
time_t curtime = ReplayMode::cur_replay.pheader.seed; time_t curtime;
if(ReplayMode::cur_replay.pheader.flag & REPLAY_UNIFORM)
curtime = ReplayMode::cur_replay.pheader.start_time;
else
curtime = ReplayMode::cur_replay.pheader.seed;
tm* st = localtime(&curtime); tm* st = localtime(&curtime);
wcsftime(infobuf, 256, L"%Y/%m/%d %H:%M:%S\n", st); wcsftime(infobuf, 256, L"%Y/%m/%d %H:%M:%S\n", st);
repinfo.append(infobuf); repinfo.append(infobuf);
......
...@@ -11,6 +11,7 @@ namespace ygo { ...@@ -11,6 +11,7 @@ namespace ygo {
#define REPLAY_TAG 0x2 #define REPLAY_TAG 0x2
#define REPLAY_DECODED 0x4 #define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8 #define REPLAY_SINGLE_MODE 0x8
#define REPLAY_UNIFORM 0x10
// max size // max size
#define MAX_REPLAY_SIZE 0x20000 #define MAX_REPLAY_SIZE 0x20000
...@@ -22,11 +23,11 @@ struct ReplayHeader { ...@@ -22,11 +23,11 @@ struct ReplayHeader {
unsigned int flag; unsigned int flag;
unsigned int seed; unsigned int seed;
unsigned int datasize; unsigned int datasize;
unsigned int hash; unsigned int start_time;
unsigned char props[8]; unsigned char props[8];
ReplayHeader() ReplayHeader()
: id(0), version(0), flag(0), seed(0), datasize(0), hash(0), props{ 0 } {} : id(0), version(0), flag(0), seed(0), datasize(0), start_time(0), props{ 0 } {}
}; };
class Replay { class Replay {
......
...@@ -153,9 +153,8 @@ int ReplayMode::ReplayThread() { ...@@ -153,9 +153,8 @@ int ReplayMode::ReplayThread() {
} }
bool ReplayMode::StartDuel() { bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader; const ReplayHeader& rh = cur_replay.pheader;
mtrandom rnd; unsigned int seed = rh.seed;
int seed = rh.seed; std::mt19937 rnd(seed);
rnd.reset(seed);
if(mainGame->dInfo.isTag) { if(mainGame->dInfo.isTag) {
cur_replay.ReadName(mainGame->dInfo.hostname); cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.hostname_tag); cur_replay.ReadName(mainGame->dInfo.hostname_tag);
...@@ -165,7 +164,7 @@ bool ReplayMode::StartDuel() { ...@@ -165,7 +164,7 @@ bool ReplayMode::StartDuel() {
cur_replay.ReadName(mainGame->dInfo.hostname); cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname); cur_replay.ReadName(mainGame->dInfo.clientname);
} }
pduel = create_duel(rnd.rand()); pduel = create_duel(rnd());
int start_lp = cur_replay.ReadInt32(); int start_lp = cur_replay.ReadInt32();
int start_hand = cur_replay.ReadInt32(); int start_hand = cur_replay.ReadInt32();
int draw_count = cur_replay.ReadInt32(); int draw_count = cur_replay.ReadInt32();
...@@ -225,13 +224,18 @@ bool ReplayMode::StartDuel() { ...@@ -225,13 +224,18 @@ bool ReplayMode::StartDuel() {
} }
} else { } else {
char filename[256]; char filename[256];
size_t slen = cur_replay.ReadInt16(); int slen = cur_replay.ReadInt16();
if (slen < 0 || slen > 255) {
return false;
}
cur_replay.ReadData(filename, slen); cur_replay.ReadData(filename, slen);
filename[slen] = 0; filename[slen] = 0;
if(!preload_script(pduel, filename, 0)) { if(!preload_script(pduel, filename, 0)) {
return false; return false;
} }
} }
if (!(rh.flag & REPLAY_UNIFORM))
opt |= DUEL_OLD_REPLAY;
start_duel(pduel, opt); start_duel(pduel, opt);
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment