summaryrefslogtreecommitdiff
path: root/src/plugin-luarand.cc
blob: db744656970bd86cc2fd820de7191882975eb102 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifdef FROM_LUAINTERFACE
#define NO_DLL
#endif

#ifndef WIN32
#define WEAK __attribute__ ((weak))
#else
#define WEAK
#endif

#include <BLua.h>

class SimpleRandom : public Base {
  public:
      SimpleRandom(Uint32 seedValue = 0) {
          if (seedValue == 0) {
              seedValue = time(NULL);
          }
          state = (seedValue | (seedValue << 32) | 1) * prime;
      }
    Uint8 GetNext() {
        state *= prime;
        return (Uint8) (state >> 21);
    }
    Uint32 GetNext32() {
        Uint32 ret = 0;

        ret <<= 8; ret | GetNext();
        ret <<= 8; ret | GetNext();
        ret <<= 8; ret | GetNext();
        ret <<= 8; ret | GetNext();

        return ret;
    }
    float GetFloat() { return (float)GetNext32() / 4294967296.0f; }
  private:
    Uint64 state;
    const static Uint64 prime = 4294967357ULL;
};

class LuaSimpleRandom : public LuaObject {
  public:
    static void pushstatics(Lua *) throw (GeneralException);
      LuaSimpleRandom(SimpleRandom * _sr) : sr(_sr) { }
  protected:
    virtual void pushmembers(Lua *);
    SimpleRandom * sr;
};

enum SimpleRandom_functions_t {
    SIMPLERANDOM_NEWSIMPLERANDOM,
};

enum SimpleRandom_methods_t {
    SIMPLERANDOM_GETNEXT,
    SIMPLERANDOM_GETNEXT32,
    SIMPLERANDOM_GETFLOAT,
};

struct lua_functypes_t SimpleRandom_functions[] = {
    { SIMPLERANDOM_NEWSIMPLERANDOM, "SimpleRandom", 0, 1, { BLUA_NUMBER } },
    { -1, 0, 0, 0, 0 },
};

struct lua_functypes_t SimpleRandom_methods[] = {
    { SIMPLERANDOM_GETNEXT,   "GetNext",   0, 0, { } },
    { SIMPLERANDOM_GETNEXT32, "GetNext32", 0, 0, { } },
    { SIMPLERANDOM_GETFLOAT,  "GetFloat",  0, 0, { } },
    { -1, 0, 0, 0, 0 },
};

class sLua_SimpleRandom : public Base {
  public:
    DECLARE_FUNCTION(SimpleRandom, SIMPLERANDOM_NEWSIMPLERANDOM);

    DECLARE_METHOD(SimpleRandom, SIMPLERANDOM_GETNEXT);
    DECLARE_METHOD(SimpleRandom, SIMPLERANDOM_GETNEXT32);
    DECLARE_METHOD(SimpleRandom, SIMPLERANDOM_GETFLOAT);
  private:
    static int SimpleRandom_proceed(Lua * L, int n, SimpleRandom * obj, int caller);
    static int SimpleRandom_proceed_statics(Lua * L, int n, int caller);
};

void LuaSimpleRandom::pushmembers(Lua * L) {
    pushme(L, sr, "SimpleRandom");

    PUSH_METHOD(SimpleRandom, SIMPLERANDOM_GETNEXT);
    PUSH_METHOD(SimpleRandom, SIMPLERANDOM_GETNEXT32);
    PUSH_METHOD(SimpleRandom, SIMPLERANDOM_GETFLOAT);
}

void LuaSimpleRandom::pushstatics(Lua * L) throw (GeneralException) {
    CHECK_METHODS(SimpleRandom);
    CHECK_FUNCTIONS(SimpleRandom);

    PUSH_FUNCTION(SimpleRandom, SIMPLERANDOM_NEWSIMPLERANDOM);
}

int sLua_SimpleRandom::SimpleRandom_proceed_statics(Lua * L, int n, int caller) {
    int r = 1;

    switch (caller) {
    case SIMPLERANDOM_NEWSIMPLERANDOM:
        {
            LuaSimpleRandom sr(new SimpleRandom(n == 1 ? L->tonumber() : 0));
            sr.pushdestruct(L);
        }
        break;
    }

    return r;
}

int sLua_SimpleRandom::SimpleRandom_proceed(Lua * L, int n, SimpleRandom * sr, int caller) {
    int r = 1;

    switch(caller) {
    case SIMPLERANDOM_GETNEXT:
        L->push((lua_Number) sr->GetNext());
        break;
    case SIMPLERANDOM_GETNEXT32:
        L->push((lua_Number) sr->GetNext32());
        break;
    case SIMPLERANDOM_GETFLOAT:
        L->push((lua_Number) sr->GetFloat());
        break;
    }

    return r;
}

static void _init_plugin(Lua * L) {
    static bool done = false;
    if (done) return;
    done = true;
    LuaSimpleRandom::pushstatics(L);
}

extern "C" {

#ifndef NO_DLL
WEAK void init_plugin(Lua * L) {
    _init_plugin(L);
}
#endif

void luarand_init(Lua * L) {
    _init_plugin(L);
}

}