Merge pull request #441 from gfgtdf/lua_random
Add wesnoth.random and sync helper.shuffle
This commit is contained in:
commit
39ffd1e37d
7 changed files with 66 additions and 19 deletions
|
@ -380,13 +380,14 @@ function helper.round( number )
|
|||
return number
|
||||
end
|
||||
|
||||
function helper.shuffle( t )
|
||||
function helper.shuffle( t, random_func)
|
||||
random_func = random_func or wesnoth.random
|
||||
-- since tables are passed by reference, this is an in-place shuffle
|
||||
-- it uses the Fisher-Yates algorithm, also known as Knuth shuffle
|
||||
assert( type( t ) == "table", string.format( "helper.shuffle expects a table as parameter, got %s instead", type( t ) ) )
|
||||
local length = #t
|
||||
for index = length, 2, -1 do
|
||||
local random = math.random( 1, index )
|
||||
local random = random_func( 1, index )
|
||||
t[index], t[random] = t[random], t[index]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include <cassert>
|
||||
#include <stdlib.h>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include <time.h>
|
||||
|
||||
static lg::log_domain log_random("random");
|
||||
#define DBG_RND LOG_STREAM(debug, log_random)
|
||||
|
@ -25,9 +27,29 @@ static lg::log_domain log_random("random");
|
|||
#define WRN_RND LOG_STREAM(warn, log_random)
|
||||
#define ERR_RND LOG_STREAM(err, log_random)
|
||||
|
||||
namespace {
|
||||
|
||||
class rng_default : public random_new::rng
|
||||
{
|
||||
public:
|
||||
rng_default()
|
||||
: gen_(time(NULL))
|
||||
{
|
||||
}
|
||||
protected:
|
||||
virtual uint32_t next_random_impl()
|
||||
{
|
||||
return gen_();
|
||||
}
|
||||
private:
|
||||
boost::mt19937 gen_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace random_new
|
||||
{
|
||||
rng* generator = new rng();
|
||||
|
||||
rng* generator = &rng::default_instance();
|
||||
|
||||
rng::rng()
|
||||
: random_calls_(0)
|
||||
|
@ -40,6 +62,12 @@ namespace random_new
|
|||
|
||||
}
|
||||
|
||||
rng& rng::default_instance()
|
||||
{
|
||||
static rng* def = new rng_default();
|
||||
return *def;
|
||||
}
|
||||
|
||||
unsigned int rng::get_random_calls()
|
||||
{
|
||||
return random_calls_;
|
||||
|
@ -71,13 +99,4 @@ namespace random_new
|
|||
assert(max >= 0);
|
||||
return static_cast<int> (next_random() % (static_cast<uint32_t>(max)+1));
|
||||
}
|
||||
|
||||
uint32_t rng::next_random_impl()
|
||||
{
|
||||
//getting here means random was called form outsiude a synced context.
|
||||
uint32_t retv = rand();
|
||||
|
||||
LOG_RND << "random_new::rng::next_random returned " << retv;
|
||||
return retv;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ namespace random_new
|
|||
*/
|
||||
int get_random_int(int min, int max)
|
||||
{ return min + get_random_int_in_range_zero_to(max - min); }
|
||||
|
||||
static rng& default_instance();
|
||||
protected:
|
||||
virtual uint32_t next_random_impl();
|
||||
virtual uint32_t next_random_impl() = 0;
|
||||
unsigned int random_calls_;
|
||||
|
||||
private:
|
||||
|
@ -68,6 +68,5 @@ namespace random_new
|
|||
Outside a synced context this has the same effect as rand()
|
||||
*/
|
||||
extern rng* generator;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1008,6 +1008,34 @@ int game_lua_kernel::intf_set_variable(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random numer, same interface as math.random.
|
||||
*/
|
||||
int game_lua_kernel::intf_random(lua_State *L)
|
||||
{
|
||||
if(lua_isnoneornil(L, 1)) {
|
||||
double r = (double)random_new::generator->next_random();
|
||||
double r_max = (double)std::numeric_limits<uint32_t>::max();
|
||||
lua_push(L, r / (r_max + 1));
|
||||
return 1;
|
||||
}
|
||||
else if(lua_isnumber(L, 1)) {
|
||||
int32_t min;
|
||||
int32_t max;
|
||||
if(lua_isnumber(L, 2)) {
|
||||
min = lua_check<int32_t>(L, 1);
|
||||
max = lua_check<int32_t>(L, 2);
|
||||
}
|
||||
else {
|
||||
min = 1;
|
||||
max = lua_check<int32_t>(L, 1);
|
||||
}
|
||||
lua_push(L, random_new::generator->get_random_int(min, max));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int game_lua_kernel::intf_set_menu_item(lua_State *L)
|
||||
{
|
||||
game_state_.get_wml_menu_items().set_item(luaL_checkstring(L, 1), luaW_checkvconfig(L,2), game_state_.events_manager_.get());
|
||||
|
@ -4098,6 +4126,7 @@ game_lua_kernel::game_lua_kernel(const config &cfg, CVideo * video, game_state &
|
|||
{ "print", &dispatch<&game_lua_kernel::intf_print > },
|
||||
{ "put_recall_unit", &dispatch<&game_lua_kernel::intf_put_recall_unit > },
|
||||
{ "put_unit", &dispatch<&game_lua_kernel::intf_put_unit > },
|
||||
{ "random", &dispatch<&game_lua_kernel::intf_random > },
|
||||
{ "redraw", &dispatch<&game_lua_kernel::intf_redraw > },
|
||||
{ "remove_event_handler", &dispatch<&game_lua_kernel::intf_remove_event > },
|
||||
{ "remove_tile_overlay", &dispatch<&game_lua_kernel::intf_remove_tile_overlay > },
|
||||
|
|
|
@ -84,6 +84,7 @@ class game_lua_kernel : public lua_kernel_base
|
|||
int intf_match_unit(lua_State *L);
|
||||
int intf_get_recall_units(lua_State *L);
|
||||
int intf_get_variable(lua_State *L);
|
||||
int intf_random(lua_State *L);
|
||||
int intf_set_variable(lua_State *L);
|
||||
int intf_highlight_hex(lua_State *L);
|
||||
int intf_is_enemy(lua_State *L);
|
||||
|
|
|
@ -503,15 +503,14 @@ int set_scontext_synced::get_random_calls()
|
|||
|
||||
|
||||
leave_synced_context::leave_synced_context()
|
||||
: new_rng_()
|
||||
, old_rng_(random_new::generator)
|
||||
: old_rng_(random_new::generator)
|
||||
{
|
||||
assert(synced_context::get_synced_state() == synced_context::SYNCED);
|
||||
synced_context::set_synced_state(synced_context::LOCAL_CHOICE);
|
||||
|
||||
//calling the synced rng form inside a local_choice would cause oos.
|
||||
//TODO: should we also reset the synced checkup?
|
||||
random_new::generator = &new_rng_;
|
||||
random_new::generator = &random_new::rng::default_instance();
|
||||
}
|
||||
|
||||
leave_synced_context::~leave_synced_context()
|
||||
|
|
|
@ -206,7 +206,6 @@ public:
|
|||
leave_synced_context();
|
||||
~leave_synced_context();
|
||||
private:
|
||||
random_new::rng new_rng_;
|
||||
random_new::rng* old_rng_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue