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;
char DuelClient::last_successful_msg[0x2000];
unsigned int DuelClient::last_successful_msg_length = 0;
wchar_t DuelClient::event_string[256];
mtrandom DuelClient::rnd;
mt19937 DuelClient::rnd;
bool DuelClient::is_refreshing = false;
int DuelClient::match_kill = 0;
......@@ -58,7 +58,7 @@ bool DuelClient::StartClient(unsigned int ip, unsigned short port, bool create_g
return false;
}
connect_state = 0x1;
rnd.reset(time(0));
rnd.reset((unsigned int)time(nullptr));
if(!create_game) {
timeval timeout = {5, 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) {
char* prep = pdata;
Replay new_replay;
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);
wchar_t timetext[40];
wcsftime(timetext, 40, L"%Y-%m-%d %H-%M-%S", localedtime);
......@@ -1651,7 +1656,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
SetResponseI(-1);
mainGame->dField.ClearChainSelect();
if(mainGame->chkWaitChain->isChecked() && !mainGame->ignore_chain) {
mainGame->WaitFrameSignal(rnd.real() * 20 + 20);
mainGame->WaitFrameSignal(rnd.get_random_integer(20, 40));
}
DuelClient::SendResponse();
return true;
......@@ -1751,7 +1756,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
if(!pzone) {
if(mainGame->chkRandomPos->isChecked()) {
do {
respbuf[2] = rnd.real() * 7;
respbuf[2] = rnd.get_random_integer(0, 6);
} while(!(filter & (1 << respbuf[2])));
} else {
if (filter & 0x40) respbuf[2] = 6;
......
......@@ -36,7 +36,7 @@ private:
static char last_successful_msg[0x2000];
static unsigned int last_successful_msg_length;
static wchar_t event_string[256];
static mtrandom rnd;
static mt19937 rnd;
public:
static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true);
static void ConnectTimeout(evutil_socket_t fd, short events, void* arg);
......
......@@ -465,7 +465,11 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break;
wchar_t infobuf[256];
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);
wcsftime(infobuf, 256, L"%Y/%m/%d %H:%M:%S\n", st);
repinfo.append(infobuf);
......
......@@ -11,6 +11,7 @@ namespace ygo {
#define REPLAY_TAG 0x2
#define REPLAY_DECODED 0x4
#define REPLAY_SINGLE_MODE 0x8
#define REPLAY_UNIFORM 0x10
// max size
#define MAX_REPLAY_SIZE 0x20000
......@@ -22,11 +23,11 @@ struct ReplayHeader {
unsigned int flag;
unsigned int seed;
unsigned int datasize;
unsigned int hash;
unsigned int start_time;
unsigned char props[8];
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 {
......
......@@ -153,9 +153,8 @@ int ReplayMode::ReplayThread() {
}
bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader;
mtrandom rnd;
int seed = rh.seed;
rnd.reset(seed);
unsigned int seed = rh.seed;
std::mt19937 rnd(seed);
if(mainGame->dInfo.isTag) {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.hostname_tag);
......@@ -165,7 +164,7 @@ bool ReplayMode::StartDuel() {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname);
}
pduel = create_duel(rnd.rand());
pduel = create_duel(rnd());
int start_lp = cur_replay.ReadInt32();
int start_hand = cur_replay.ReadInt32();
int draw_count = cur_replay.ReadInt32();
......@@ -225,13 +224,18 @@ bool ReplayMode::StartDuel() {
}
} else {
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);
filename[slen] = 0;
if(!preload_script(pduel, filename, 0)) {
return false;
}
}
if (!(rh.flag & REPLAY_UNIFORM))
opt |= DUEL_OLD_REPLAY;
start_duel(pduel, opt);
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