Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ srand, rand in a DLL strange behavior

I'm doing a host for an AI contest, and have a randomBot that choice random possible values.

The bot has 2 exported functions: Init(_seed) and MakeMove()

To play exactly same games host have a defined seed value for each bot. and its passes it in the Init function.

The Init function of random bot has a srand(_seed) function call. The MakeMove function of random bot has a rand() function call.

Now the problem is that after loading 2 bots, each game should be the same with the same seed values, but they are different.

As I know srand should store its value per module/thread and not share it.

I made a test and created a function mysrand and myrand that are not exported with calls to srand and rand respectively.

I replaced the srand and rand inside the exported functions with mysrand and myrand... and it worked...

I have a clue why this is happening but not sure...

So why exactly does it happen and how to avoid it because I want the contestants to use any function they want inside the exported functions (don't want to use my proxy functions).

Thanks.

I'm using windows, compilers: gcc, visual C++, borland C++ builder

like image 223
Spider Avatar asked Jun 10 '12 04:06

Spider


1 Answers

If you want to get consistent behavior the <random> library is probably a better choice. You can control where the RNG's state is stored and the engines can produce the same values across implementations (although the standard distributions aren't required to produce the same output across implementations).

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] {
        // A simple example distribution function; not intended for real use.
        return static_cast<int>(eng()/static_cast<double>(eng.max() + 1ull) * 20.0) + 1;
    });
}

This should output the following on all implementations:

17 3 19 17 3 20 19 5 13 7

If you only need consistent behavior within an implementation and not across implementations then you can use the standard distributions, and you'll still have control over where the RNG's state is.

#include <random>
#include <iterator>
#include <algorithm>
#include <iostream>

int main() {
    std::mt19937 eng;
    std::uniform_int_distribution<> dist(1,20);
    std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, [&] { return dist(eng); });
}

The standard distributions should be preferred over writing your own.

like image 90
bames53 Avatar answered Sep 23 '22 19:09

bames53