diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua index 2e4dadee88c05b47e9fcd9b76788a709dcaf0ebc..a953d5dbf889fd5ddf1c352ebd508e9798af1b2c 100644 --- a/game/engine/Actor.lua +++ b/game/engine/Actor.lua @@ -7,7 +7,9 @@ module(..., package.seeall, class.inherit(Entity)) function _M:init(t) t = t or {} self.name = t.name - self.energy = { value=0, mod=1 } + self.energy = t.energy or { value=0, mod=1 } + self.energy.value = self.energy.value or 0 + self.energy.mod = self.energy.mod or 0 Entity.init(self, t) end diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua index ca7ba449fa131f0ddfa6d5b7b7cc73b6e6253e34..0d95165e205650e37280c6eb3512a7017a041274 100644 --- a/game/engine/Entity.lua +++ b/game/engine/Entity.lua @@ -36,3 +36,19 @@ function _M:check(prop, ...) else return self[prop] end end + +function _M:loadList(...) + local res = {} + + for i, file in ipairs{...} do + local f, err = loadfile(file) + if err then error(err) end + local data = f() + for i, a in ipairs(data) do + local e = self.new(a) + res[#res+1] = e + if a.define_as then res[a.define_as] = e end + end + end + return res +end diff --git a/game/engine/Game.lua b/game/engine/Game.lua index aa7ac62433685c578ffa1570ab751303854cb347..571e1940a0372cff8d8acdf08304add84dbc2415 100644 --- a/game/engine/Game.lua +++ b/game/engine/Game.lua @@ -7,6 +7,9 @@ function _M:init(keyhandler) self.w, self.h = core.display.size() end +function _M:run() +end + function _M:setLevel(level) self.level = level end diff --git a/game/engine/GameEnergyBased.lua b/game/engine/GameEnergyBased.lua index 1d9cd5be5b132e00e62988f7bb2f053e0a553264..f7a2147c75a5696856e9a76d4db91c0803bcac61 100644 --- a/game/engine/GameEnergyBased.lua +++ b/game/engine/GameEnergyBased.lua @@ -11,12 +11,14 @@ function _M:tick() engine.Game.tick(self) -- Give some energy to entities - for uid, e in pairs(self.level.entities) do - if e.energy and e.energy.value < self.energy_to_act then - e.energy.value = (e.energy.value or 0) + self.energy_per_tick * (e.energy.mod or 1) --- print(e.uid, e.energy.value) - if e.energy.value >= self.energy_to_act and e.act then - e:act(self) + if self.level then + for uid, e in pairs(self.level.entities) do + if e.energy and e.energy.value < self.energy_to_act then + e.energy.value = (e.energy.value or 0) + self.energy_per_tick * (e.energy.mod or 1) +-- print(e.uid, e.energy.value) + if e.energy.value >= self.energy_to_act and e.act then + e:act(self) + end end end end diff --git a/game/engine/Grid.lua b/game/engine/Grid.lua new file mode 100644 index 0000000000000000000000000000000000000000..d7647275b2ed1abc115c351bd6e2ca2fbaf14e38 --- /dev/null +++ b/game/engine/Grid.lua @@ -0,0 +1,10 @@ +require "engine.class" +local Entity = require "engine.Entity" + +module(..., package.seeall, class.inherit(Entity)) + +function _M:init(t) + t = t or {} + self.name = t.name + Entity.init(self, t) +end diff --git a/game/engine/Map.lua b/game/engine/Map.lua index 1ca4b36fd511aa799f33629176c1bd54fa10be14..8ef15670e8418d46f2db71fa178bf555db7cc7c1 100644 --- a/game/engine/Map.lua +++ b/game/engine/Map.lua @@ -159,3 +159,9 @@ function _M:liteAll(x, y, w, h) self.lites(i, j, true) end end end + +function _M:rememberAll(x, y, w, h) + for i = x, x + w - 1 do for j = y, y + h - 1 do + self.remembers(i, j, true) + end end +end diff --git a/game/engine/MapGenerator.lua b/game/engine/MapGenerator.lua new file mode 100644 index 0000000000000000000000000000000000000000..86003a2b103f5be682a098169debd6e3cbecad7b --- /dev/null +++ b/game/engine/MapGenerator.lua @@ -0,0 +1,10 @@ +require "engine.class" +module(..., package.seeall, class.make) + +function _M:init(map) + self.map = map +end + +function _M:generate() + +end diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua new file mode 100644 index 0000000000000000000000000000000000000000..13bdae76e80b69a5baefcd1fe634d5cad621c397 --- /dev/null +++ b/game/engine/Zone.lua @@ -0,0 +1,25 @@ +module(..., package.seeall, class.make) + +-- Static method +-- Setup classes to use for entities +function _M:setup(t) + self.npc_class = require(t.npc_class) + self.grid_class = require(t.grid_class) + self.object_class = require(t.object_class) +end + +function _M:init(short_name) + self.short_name = short_name + self:load() + self.levels = self.levels or {} + self.npc_list = self.npc_class:loadList("/data/zones/"..self.short_name.."/npcs.lua") + self.grid_list = self.grid_class:loadList("/data/zones/"..self.short_name.."/grids.lua") + self.object_list = self.object_class:loadList("/data/zones/"..self.short_name.."/objects.lua") +end + +function _M:load() + local f, err = loadfile("/data/zones/"..self.short_name.."/zone.lua") + if err then error(err) end + local data = f() + +end diff --git a/game/engine/class.lua b/game/engine/class.lua index 3229280b27b2893bbc26c6901b9d03db93c03959..3f6da8f5aefbb6b297c8b9759219604d3a73736a 100644 --- a/game/engine/class.lua +++ b/game/engine/class.lua @@ -6,6 +6,7 @@ function make(c) setmetatable(c, {__index=_M}) c.new = function(...) local obj = {} + obj.__CLASSNAME = c._NAME setmetatable(obj, {__index=c}) if obj.init then obj:init(...) end return obj @@ -18,6 +19,7 @@ function inherit(base) setmetatable(c, {__index=base}) c.new = function(...) local obj = {} + obj.__CLASSNAME = c._NAME setmetatable(obj, {__index=c}) if obj.init then obj:init(...) end return obj @@ -26,17 +28,109 @@ function inherit(base) end end -function _M:clone(t, deep) +function _M:getClassName() + return self.__CLASSNAME +end + +function _M:getClass() + return getmetatble(self).__index +end + +local function clonerecurs(d) local n = {} - for k, e in pairs(self) do - n[k] = e + for k, e in pairs(d) do + local nk, ne = k, e + if type(k) == "table" then nk = clonerecurs(k) end + if type(e) == "table" then ne = clonerecurs(e) end + n[nk] = ne + end + return n +end +--[[ +local function cloneadd(dest, src) + for k, e in pairs(src) do + local nk, ne = k, e + if type(k) == "table" then nk = cloneadd(k) end + if type(e) == "table" then ne = cloneadd(e) end + dest[nk] = ne end +end +]] +function _M:clone(t) + local n = clonerecurs(self) if t then - for k, e in pairs(t) do - n[k] = e - end +-- error("cloning mutation not yet implemented") +-- cloneadd(n, t) + for k, e in pairs(t) do n[k] = e end end setmetatable(n, getmetatable(self)) if n.cloned then n:cloned(self) end return n end + +----------------------------------------------------------------------- +----------------------------------------------------------------------- +-- LOAD & SAVE +----------------------------------------------------------------------- +----------------------------------------------------------------------- +local function basicSerialize(o) + if type(o) == "number" or type(o) == "boolean" then + return tostring(o) + elseif type(o) == "function" then + return string.format("%q", string.dump(o)) + else -- assume it is a string + return string.format("%q", o) + end +end + +local function serialize_data(outf, name, value, saved, filter) + saved = saved or {} -- initial value + outf(name, " = ") + if type(value) == "number" or type(value) == "string" or type(value) == "boolean" or type(value) == "function" then + outf(basicSerialize(value), "\n") + elseif type(value) == "table" then + if saved[value] then -- value already saved? + outf(saved[value], "\n") -- use its previous name + else + saved[value] = name -- save name for next time + outf("{}\n") -- create a new table + for k,v in pairs(value) do -- save its fields + if not filter[k] then + local fieldname = string.format("%s[%s]", name, basicSerialize(k)) + serialize_data(outf, fieldname, v, saved, filter) + end + end + end + else + error("cannot save a " .. type(value) .. " ("..name..")") + end +end + +local function serialize(data, filter) + local tbl = {} + local outf = function(...) for i,str in ipairs(arg) do table.insert(tbl, str) end end + serialize_data(outf, "data", data, nil, filter) + table.insert(tbl, "return data\n") + return tbl +end + +local function deserialize(string) + local f = loadstring(string) + setfenv(f, {}) + return f() +end + +function _M:save(filter) + filter = filter or {} + filter.new = true + return table.concat(serialize(self, filter)) +end + +function load(str) + local obj = deserialize(str) + if obj then + setmetatable(obj, {__index=require(obj.__CLASSNAME)}) + if obj.loaded then obj:loaded() end + end + return obj +end diff --git a/game/engine/generator/BST.lua b/game/engine/generator/BST.lua new file mode 100644 index 0000000000000000000000000000000000000000..686b2934fb08d00a77cd1a4cb99ddb9794d65100 --- /dev/null +++ b/game/engine/generator/BST.lua @@ -0,0 +1,67 @@ +require "engine.class" +require "engine.MapGenerator" +module(..., package.seeall, class.inherit(engine.MapGenerator)) + +function _M:init(map, splitzone, floor, wall) + engine.MapGenerator.init(self, map) + self.smallest = 100000 + self.tree = {} + self.splitzone = splitzone + self.floor, self.wall = floor, wall +end + +function _M:split(x, y, w, h) + local x1, y1, w1, h1 + local x2, y2, w2, h2 + local split, dir + if rng.chance(2) then + split = rng.range(w * self.splitzone[1], w * self.splitzone[2]) + x1, y1, w1, h1 = x, y, split, h + x2, y2, w2, h2 = x + split, y, w - split, h + else + split = rng.range(h * self.splitzone[1], h * self.splitzone[2]) + x1, y1, w1, h1 = x, y, w, split + x2, y2, w2, h2 = x, y + split, w, h - split + print(x1, y1, w1, h1) + print(x2, y2, w2, h2) + end + return {x1, y1, w1, h1}, {x2, y2, w2, h2} +end + +function _M:fill(t) + for i = t[1], t[1] + t[3] - 1 do + for j = t[2], t[2] + t[4] - 1 do + if i == t[1] or i == t[1] + t[3] - 1 or j == t[2] or j == t[2] + t[4] - 1 then + self.map(i, j, engine.Map.TERRAIN, self.wall) + else + self.map(i, j, engine.Map.TERRAIN, self.floor) + end + end + end +end + +function _M:roomSize(t) + return t[3] * t[4] +end + +function _M:generate() + local process = { {0, 0, self.map.w, self.map.h} } + local rooms = {} + while #process > 0 do + local baser = table.remove(process, 1) + + local r1, r2 = self:split(unpack(baser)) + + if self:roomSize(r1) <= 40 or self:roomSize(r2) <= 40 or r1[3] < 6 or r1[4] < 6 or r2[3] < 6 or r2[4] < 6 then + table.insert(rooms, r1) + table.insert(rooms, r2) + else + table.insert(process, r1) + table.insert(process, r2) + end + end + + for i, r in ipairs(rooms) do + self:fill(r) + end +end diff --git a/game/engine/init.lua b/game/engine/init.lua index 7a9ea48ced3b45d0f30790a61330b993bdb38c34..9892664012275b78eb11c412489747ff75036573 100644 --- a/game/engine/init.lua +++ b/game/engine/init.lua @@ -14,7 +14,8 @@ key:addCommand(key._x, {"ctrl"}, function() os.exit() end) key:addCommand(key._RETURN, {"alt"}, function() core.display.fullscreen() end) -- Load the game module -local mod_def = loadfile("/tome/init.lua") +game = false +local mod_def = loadfile("/mod/init.lua") if mod_def then local mod = {} setfenv(mod_def, mod) @@ -22,8 +23,9 @@ if mod_def then if not mod.name or not mod.short_name or not mod.version or not mod.starter then os.exit() end - engine.Tiles.prefix = "/"..mod.short_name.."/data/gfx/" - require(mod.starter) + engine.Tiles.prefix = "/data/gfx/" + game = dofile("/"..mod.starter:gsub("%.", "/")..".lua") + game:run() else os.exit() end diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua index 451584890343b3681069766a90d8103b260c4906..2670d91216e57b99521e656368e75b85492282d5 100644 --- a/game/modules/tome/class/Actor.lua +++ b/game/modules/tome/class/Actor.lua @@ -3,29 +3,34 @@ require "engine.Actor" module(..., package.seeall, class.inherit(engine.Actor)) -function _M:init(game, t) +function _M:init(t) t.block_move = _M.bumped - engine.Actor.init(self, t) - - self.game = game + self.level = 1 self.life = 100 + self.mana = 100 + self.skills = {} + self.attacks = {} + engine.Actor.init(self, t) +end - self.tooltip = _M.tooltip +-- When saving, ignore some fields +function _M:save() + return engine.Actor.save(self, {game=true}) end function _M:move(x, y, force) local moved = false - if force or self.energy.value >= self.game.energy_to_act then - moved = engine.Actor.move(self, self.game.level.map, x, y) - if not force then self.energy.value = self.energy.value - self.game.energy_to_act end + if force or self.energy.value >= game.energy_to_act then + moved = engine.Actor.move(self, game.level.map, x, y) + if not force then self.energy.value = self.energy.value - game.energy_to_act end end return moved end function _M:bumped(x, y, e) -- Dont bump yourself! - if e ~= self then - self.game.log("%s bumped into %s!", tostring(e.name), tostring(self.name)) + if e and e ~= self then + game.log("%s bumped into %s!", tostring(e.name), tostring(self.name)) end return true end diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 075e544f3d34bd81679efc8dd087c443c128b203..acfe9de0514d4d4c6e988c84282190472b10ebdd 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -3,57 +3,56 @@ require "engine.GameTurnBased" require "engine.KeyCommand" require "engine.LogDisplay" local Tooltip = require "engine.Tooltip" +local BST = require "engine.generator.BST" +local Zone = require "engine.Zone" local Map = require "engine.Map" local Level = require "engine.Level" -local Entity = require "engine.Entity" -local Player = require "tome.class.Player" -local NPC = require "tome.class.NPC" +local Grid = require "engine.Grid" +local Actor = require "mod.class.Actor" +local Player = require "mod.class.Player" +local NPC = require "mod.class.NPC" module(..., package.seeall, class.inherit(engine.GameTurnBased)) function _M:init() engine.GameTurnBased.init(self, engine.Key.current, 1000, 100) +end + +function _M:run() self:setupCommands() + Zone:setup{npc_class="mod.class.NPC", grid_class="engine.Grid", object_class="engine.Entity"} + self.zone = Zone.new("ancient_ruins") + self.tooltip = engine.Tooltip.new(nil, nil, {255,255,255}, {30,30,30}) self.log = engine.LogDisplay.new(self.w * 0.5, self.h * 0.20, nil, nil, nil, {255,255,255}, {30,30,30}) self.log("Welcome to #00FF00#Tales of Middle Earth!") local map = Map.new(self.w, math.floor(self.h * 0.80), 16, 16) --- map:liteAll(0, 0, map.w, map.h) - - local floor = Entity.new{display='.', color_r=100, color_g=200, color_b=100, color_br=0, color_bg=50, color_bb=0} - local e1 = Entity.new{display='#', color_r=255, block_sight=true, block_move=true} - local e2 = Entity.new{display='#', color_g=255, block_sight=true, block_move=true} - local e3 = Entity.new{display='#', color_b=255, block_sight=true, block_move=true} - local e4 = e3:clone{color_r=255} - - for i = 0, map.w-1 do for j = 0, map.h-1 do - map(i, j, 1, floor) - end end - - map(8, 6, Map.TERRAIN, e4) - map(8, 7, Map.TERRAIN, e2) - map(8, 8, Map.TERRAIN, e3) - map(9, 6, Map.TERRAIN, e1) - map(9, 7, Map.TERRAIN, e2) - map(9, 8, Map.TERRAIN, e3) - map(10, 6, Map.TERRAIN, e1) - map(10, 7, Map.TERRAIN, e2) - map(10, 8, Map.TERRAIN, e3) + map:liteAll(0, 0, map.w, map.h) + map:rememberAll(0, 0, map.w, map.h) + + local floor = self.zone.grid_list.GRASS + local wall = self.zone.grid_list.TREE + + local generator = BST.new(map, {0.4, 0.6}, floor, wall) + generator:generate() local level = Level.new(map) self:setLevel(level) - self.player = Player.new(self, {name="player", image='player.png', display='@', color_r=230, color_g=230, color_b=230}) + self.player = Player.new{name="player", image='player.png', display='@', color_r=230, color_g=230, color_b=230} self.player:move(4, 3, true) level:addEntity(self.player) - local m = NPC.new(self, {name="here be dragons", display='D', color_r=125, color_g=125, color_b=255}) - m.energy.mod = 0.38 - m:move(1, 3, true) - level:addEntity(m) + for i = 1, 5 do +-- local m = self.npc_list[rng.range(1, 2)]:clone() +-- level:addEntity(m) +-- local x, y = rng.range(0, map.w), rng.range(0, map.h) +-- while map:checkAllEntity(x, y, "block_move") do x, y = rng.range(0, map.w), rng.range(0, map.h) end +-- m:move(x, y, true) + end -- Ok everything is good to go, activate the game in the engine! self:setCurrent() diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua index e4671c9d9909da56808253f369485651c1eef96e..2b1a4ee9bc780a0622ab34c8240a890d9e3cf1d6 100644 --- a/game/modules/tome/class/NPC.lua +++ b/game/modules/tome/class/NPC.lua @@ -1,10 +1,10 @@ require "engine.class" -require "tome.class.Actor" +require "mod.class.Actor" -module(..., package.seeall, class.inherit(tome.class.Actor)) +module(..., package.seeall, class.inherit(mod.class.Actor)) -function _M:init(game, t) - tome.class.Actor.init(self, game, t) +function _M:init(t) + mod.class.Actor.init(self, t) end function _M:act() diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua index 68efb34cb721df156d0275fb8b38e560a6ed5032..60bc38e1b892e7e5cbe39bf463023f32befd5a92 100644 --- a/game/modules/tome/class/Player.lua +++ b/game/modules/tome/class/Player.lua @@ -1,17 +1,17 @@ require "engine.class" -require "tome.class.Actor" +require "mod.class.Actor" -module(..., package.seeall, class.inherit(tome.class.Actor)) +module(..., package.seeall, class.inherit(mod.class.Actor)) -function _M:init(game, t) - tome.class.Actor.init(self, game, t) +function _M:init(t) + mod.class.Actor.init(self, t) end function _M:move(x, y, force) - local moved = tome.class.Actor.move(self, x, y, force) + local moved = mod.class.Actor.move(self, x, y, force) return moved end function _M:act() - self.game.paused = true + game.paused = true end diff --git a/game/modules/tome/data/zones/ancient_ruins/grids.lua b/game/modules/tome/data/zones/ancient_ruins/grids.lua new file mode 100644 index 0000000000000000000000000000000000000000..0a5ffb2ad5d1bc8c6c19cdbac6580663b4decff7 --- /dev/null +++ b/game/modules/tome/data/zones/ancient_ruins/grids.lua @@ -0,0 +1,16 @@ +return { + +{ + define_as = "GRASS", + name = "grass", + display = ".", color_g=255, +}, +{ + define_as = "TREE", + name = "tree", + display = "#", color_g=200, + block_move = true, + block_sight = true, +}, + +} diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua new file mode 100644 index 0000000000000000000000000000000000000000..53bfb522fdaf1fe4c587641f4a1d4e832aecf506 --- /dev/null +++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua @@ -0,0 +1,18 @@ +return { + +{ + name = "dragon of death", + display = "D", color_r=255, + life = 1000, + mana = 1000, + energy = { mod=0.8 }, +}, +{ + name = "baby dragon", + display = "d", color_r=128, + life = 1000, + mana = 1000, + energy = { mod=0.3 }, +}, + +} \ No newline at end of file diff --git a/game/modules/tome/data/zones/ancient_ruins/objects.lua b/game/modules/tome/data/zones/ancient_ruins/objects.lua new file mode 100644 index 0000000000000000000000000000000000000000..97aeaddb9693cea76493f6bab55c6c575b824967 --- /dev/null +++ b/game/modules/tome/data/zones/ancient_ruins/objects.lua @@ -0,0 +1,2 @@ +return { +} diff --git a/game/modules/tome/data/zones/ancient_ruins/zone.lua b/game/modules/tome/data/zones/ancient_ruins/zone.lua new file mode 100644 index 0000000000000000000000000000000000000000..97aeaddb9693cea76493f6bab55c6c575b824967 --- /dev/null +++ b/game/modules/tome/data/zones/ancient_ruins/zone.lua @@ -0,0 +1,2 @@ +return { +} diff --git a/game/modules/tome/init.lua b/game/modules/tome/init.lua index 5cb83b42d4a77aa31a7bd25bf5887b9ec07f6b33..2cccdc31ac5f5201b4c2df02c9f91ac5b78be60a 100644 --- a/game/modules/tome/init.lua +++ b/game/modules/tome/init.lua @@ -1,4 +1,4 @@ name = "Tales of Middle Earth" short_name = "tome" version = {4,0,0} -starter = "tome.load" +starter = "mod.load" diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua index 7c09e013437c37bb9cd529b83e8069464957c38a..59af8ca1b67a9e585f9c86ebd26f8db39d736be6 100644 --- a/game/modules/tome/load.lua +++ b/game/modules/tome/load.lua @@ -1,4 +1,6 @@ -local Game = require "tome.class.Game" +local Game = require "mod.class.Game" +-- Global local game = Game.new() game:setCurrent() +return game diff --git a/src/SFMT.c b/src/SFMT.c index 347235c2440076ba1217f83b6c7ad9dead0dbdda..7ae7f5e0853e94aec2dca73afd96372e2428f4c8 100644 --- a/src/SFMT.c +++ b/src/SFMT.c @@ -1,4 +1,4 @@ -/** +/** * @file SFMT.c * @brief SIMD oriented Fast Mersenne Twister(SFMT) * @@ -35,7 +35,7 @@ typedef struct W128_T w128_t; /*-------------------------------------- FILE GLOBAL VARIABLES - internal state, index counter and flag + internal state, index counter and flag --------------------------------------*/ /** the 128-bit internal state array */ static w128_t sfmt[N]; @@ -75,7 +75,7 @@ inline static void swap(w128_t array[], int size); #endif /** - * This function simulate a 64-bit index of LITTLE ENDIAN + * This function simulate a 64-bit index of LITTLE ENDIAN * in BIG ENDIAN machine. */ #ifdef ONLY64 @@ -182,13 +182,13 @@ inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, lshift128(&x, a, SL2); rshift128(&y, c, SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] + r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK2) ^ y.u[0] ^ (d->u[0] << SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] + r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK1) ^ y.u[1] ^ (d->u[1] << SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] + r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK4) ^ y.u[2] ^ (d->u[2] << SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] + r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK3) ^ y.u[3] ^ (d->u[3] << SL1); } #else @@ -199,13 +199,13 @@ inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *c, lshift128(&x, a, SL2); rshift128(&y, c, SR2); - r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] + r->u[0] = a->u[0] ^ x.u[0] ^ ((b->u[0] >> SR1) & MSK1) ^ y.u[0] ^ (d->u[0] << SL1); - r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] + r->u[1] = a->u[1] ^ x.u[1] ^ ((b->u[1] >> SR1) & MSK2) ^ y.u[1] ^ (d->u[1] << SL1); - r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] + r->u[2] = a->u[2] ^ x.u[2] ^ ((b->u[2] >> SR1) & MSK3) ^ y.u[2] ^ (d->u[2] << SL1); - r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] + r->u[3] = a->u[3] ^ x.u[3] ^ ((b->u[3] >> SR1) & MSK4) ^ y.u[3] ^ (d->u[3] << SL1); } #endif @@ -237,7 +237,7 @@ inline static void gen_rand_all(void) { * This function fills the user-specified array with pseudorandom * integers. * - * @param array an 128-bit array to be filled by pseudorandom numbers. + * @param array an 128-bit array to be filled by pseudorandom numbers. * @param size number of 128-bit pseudorandom numbers to be generated. */ inline static void gen_rand_array(w128_t array[], int size) { @@ -392,7 +392,7 @@ inline uint32_t gen_rand32(void) { * This function generates and returns 64-bit pseudorandom number. * init_gen_rand or init_by_array must be called before this function. * The function gen_rand64 should not be called after gen_rand32, - * unless an initialization is again executed. + * unless an initialization is again executed. * @return 64-bit pseudorandom number */ inline uint64_t gen_rand64(void) { @@ -508,7 +508,7 @@ void init_gen_rand(uint32_t seed) { psfmt32[idxof(0)] = seed; for (i = 1; i < N32; i++) { - psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] + psfmt32[idxof(i)] = 1812433253UL * (psfmt32[idxof(i - 1)] ^ (psfmt32[idxof(i - 1)] >> 30)) + i; } @@ -547,7 +547,7 @@ void init_by_array(uint32_t init_key[], int key_length) { } else { count = N32; } - r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] + r = func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid)] ^ psfmt32[idxof(N32 - 1)]); psfmt32[idxof(mid)] += r; r += key_length; @@ -556,7 +556,7 @@ void init_by_array(uint32_t init_key[], int key_length) { i = 1; count--; for (i = 1, j = 0; (j < count) && (j < key_length); j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] + r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] ^ psfmt32[idxof((i + N32 - 1) % N32)]); psfmt32[idxof((i + mid) % N32)] += r; r += init_key[j] + i; @@ -565,7 +565,7 @@ void init_by_array(uint32_t init_key[], int key_length) { i = (i + 1) % N32; } for (; j < count; j++) { - r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] + r = func1(psfmt32[idxof(i)] ^ psfmt32[idxof((i + mid) % N32)] ^ psfmt32[idxof((i + N32 - 1) % N32)]); psfmt32[idxof((i + mid) % N32)] += r; r += i; @@ -574,7 +574,7 @@ void init_by_array(uint32_t init_key[], int key_length) { i = (i + 1) % N32; } for (j = 0; j < N32; j++) { - r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] + r = func2(psfmt32[idxof(i)] + psfmt32[idxof((i + mid) % N32)] + psfmt32[idxof((i + N32 - 1) % N32)]); psfmt32[idxof((i + mid) % N32)] ^= r; r -= i; @@ -587,3 +587,25 @@ void init_by_array(uint32_t init_key[], int key_length) { period_certification(); initialized = 1; } + +uint32_t rand_div(uint32_t m) +{ + uint32_t r, n; + + /* Hack -- simple case */ + if (m <= 1) return (0); + + uint32_t used = m; + used |= used >> 1; + used |= used >> 2; + used |= used >> 4; + used |= used >> 8; + used |= used >> 16; + + // Draw numbers until one is found in [0,n] + do r = gen_rand32() & used; // toss unused bits to shorten search + while( r >= m ); + + /* Use the value */ + return (r); +} diff --git a/src/SFMT.h b/src/SFMT.h index fec9ec2dc124b4c55d1cab3dc5ae8000e477c75e..15339bd33d213aa050ab3074e084f96047b83d39 100644 --- a/src/SFMT.h +++ b/src/SFMT.h @@ -1,5 +1,5 @@ -/** - * @file SFMT.h +/** + * @file SFMT.h * * @brief SIMD oriented Fast Mersenne Twister(SFMT) pseudorandom * number generator @@ -18,7 +18,7 @@ * and you have to define PRIu64 and PRIx64 in this file as follows: * @verbatim typedef unsigned int uint32_t - typedef unsigned long long uint64_t + typedef unsigned long long uint64_t #define PRIu64 "llu" #define PRIx64 "llx" @endverbatim @@ -65,13 +65,14 @@ void init_by_array(uint32_t init_key[], int key_length); char *get_idstring(void); int get_min_array_size32(void); int get_min_array_size64(void); +uint32_t rand_div(uint32_t m); /* These real versions are due to Isaku Wada */ /** generates a random number on [0,1]-real-interval */ inline static double to_real1(uint32_t v) { - return v * (1.0/4294967295.0); - /* divided by 2^32-1 */ + return v * (1.0/4294967295.0); + /* divided by 2^32-1 */ } /** generates a random number on [0,1]-real-interval */ @@ -83,7 +84,7 @@ inline static double genrand_real1(void) /** generates a random number on [0,1)-real-interval */ inline static double to_real2(uint32_t v) { - return v * (1.0/4294967296.0); + return v * (1.0/4294967296.0); /* divided by 2^32 */ } @@ -96,7 +97,7 @@ inline static double genrand_real2(void) /** generates a random number on (0,1)-real-interval */ inline static double to_real3(uint32_t v) { - return (((double)v) + 0.5)*(1.0/4294967296.0); + return (((double)v) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ } @@ -108,14 +109,14 @@ inline static double genrand_real3(void) /** These real versions are due to Isaku Wada */ /** generates a random number on [0,1) with 53-bit resolution*/ -inline static double to_res53(uint64_t v) -{ +inline static double to_res53(uint64_t v) +{ return v * (1.0/18446744073709551616.0L); } /** generates a random number on [0,1) with 53-bit resolution*/ -inline static double genrand_res53(void) -{ +inline static double genrand_res53(void) +{ return to_res53(gen_rand64()); -} +} #endif diff --git a/src/core_lua.c b/src/core_lua.c index 81b6836a2bb92653c55ba3a51b8ff9e25fec9062..20a9e667c4345b6b0d3d8144de93d93d9c24c889 100644 --- a/src/core_lua.c +++ b/src/core_lua.c @@ -6,6 +6,7 @@ #include "types.h" #include "script.h" #include "display.h" +#include "SFMT.h" #include "sge.h" #include <SDL_ttf.h> @@ -393,6 +394,65 @@ static const struct luaL_reg sdl_font_reg[] = {NULL, NULL}, }; +/****************************************************************** + ****************************************************************** + * RNG * + ****************************************************************** + ******************************************************************/ + +static int rng_dice(lua_State *L) +{ + int x = luaL_checknumber(L, 1); + int y = luaL_checknumber(L, 2); + int i, res = 0; + for (i = 0; i < x; i++) + res += 1 + rand_div(y); + lua_pushnumber(L, res); + return 1; +} + +static int rng_range(lua_State *L) +{ + int x = luaL_checknumber(L, 1); + int y = luaL_checknumber(L, 2); + lua_pushnumber(L, x + rand_div(1 + y - x)); + return 1; +} + +static int rng_call(lua_State *L) +{ + int x = luaL_checknumber(L, 1); + lua_pushnumber(L, rand_div(x)); + return 1; +} + +static int rng_seed(lua_State *L) +{ + int seed = luaL_checknumber(L, 1); + if (seed>=0) + init_gen_rand(seed); + else + init_gen_rand(time(NULL)); + return 0; +} + +static int rng_chance(lua_State *L) +{ + int x = luaL_checknumber(L, 1); + lua_pushboolean(L, rand_div(x) == 0); + return 1; +} + +static const struct luaL_reg rnglib[] = +{ + {"__call", rng_call}, + {"range", rng_range}, + {"dice", rng_dice}, + {"seed", rng_seed}, + {"chance", rng_chance}, + {NULL, NULL}, +}; + int luaopen_core(lua_State *L) { auxiliar_newclass(L, "fov{core}", fov_reg); @@ -403,5 +463,6 @@ int luaopen_core(lua_State *L) luaL_openlib(L, "core.mouse", mouselib, 0); luaL_openlib(L, "core.key", keylib, 0); luaL_openlib(L, "core.game", gamelib, 0); + luaL_openlib(L, "rng", rnglib, 0); return 1; } diff --git a/src/main.c b/src/main.c index 48bd4032489d243b2d155414ba24bc09570cf815..d4a5ff5a6ba6256108eaae0d272921dbd58a8366 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,7 @@ #include "lauxlib.h" #include "lualib.h" #include "fov/fov.h" +#include "SFMT.h" #include "sge.h" #include "types.h" @@ -121,10 +122,14 @@ static int docall (lua_State *L, int narg, int clear) { */ int run(int argc, char *argv[]) { + // RNG init + init_gen_rand(time(NULL)); + /***************** Physfs Init *****************/ PHYSFS_init(argv[0]); PHYSFS_mount("game/", "/", 1); - PHYSFS_mount("game/modules/tome", "/tome", 1); + PHYSFS_mount("game/modules/tome", "/mod", 1); + PHYSFS_mount("game/modules/tome/data", "/data", 1); /***************** Lua Init *****************/ L = lua_open(); /* create state */