The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
mapgen_lua_kernel.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2016 by Chris Beck <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 
17 #include "config.hpp"
18 #include "game_errors.hpp"
19 #include "log.hpp"
20 #include "scripting/lua_api.hpp"
21 #include "scripting/lua_common.hpp"
22 #include "scripting/lua_rng.hpp"
24 
25 #include <ostream>
26 #include <string>
27 #include "utils/functional.hpp"
28 
29 #include "lua/lauxlib.h"
30 #include "lua/lua.h"
31 #include "scripting/push_check.hpp"
32 
33 static lg::log_domain log_mapgen("mapgen");
34 #define ERR_NG LOG_STREAM(err, log_mapgen)
35 #define LOG_NG LOG_STREAM(info, log_mapgen)
36 #define DBG_NG LOG_STREAM(debug, log_mapgen)
37 
38 struct lua_State;
39 
40 
41 
42 /**
43  * Returns a random numer, same interface as math.random.
44  */
45 static int intf_random(lua_State *L)
46 {
47  boost::mt19937& rng = lua_kernel_base::get_lua_kernel<mapgen_lua_kernel>(L).get_default_rng();
48  if(lua_isnoneornil(L, 1)) {
49  double r = double (rng());
50  double r_max = double (rng.max());
51  lua_push(L, r / (r_max + 1));
52  return 1;
53  }
54  else {
55  int32_t min;
56  int32_t max;
57  if(lua_isnumber(L, 2)) {
58  min = lua_check<int32_t>(L, 1);
59  max = lua_check<int32_t>(L, 2);
60  }
61  else {
62  min = 1;
63  max = lua_check<int32_t>(L, 1);
64  }
65  if(min > max) {
66  return luaL_argerror(L, 1, "min > max");
67  }
68  lua_push(L, min + static_cast<int>(rng() % (max - min + 1)));
69  return 1;
70  }
71 }
72 
73 /**
74  * Finds a path between two locations.
75  * - Args 1,2: source location.
76  * - Args 3,4: destination.
77  * - Arg 5: cost function
78  * - Args 6,7 size of map.
79  * - Arg 8 include border.
80  * - Ret 1: array of pairs containing path steps.
81  * - Ret 2: path cost.
82  */
83 static int intf_find_path(lua_State *L)
84 {
85  int arg = 1;
87  src.x = luaL_checkinteger(L, 1) - 1;
88  src.y = luaL_checkinteger(L, 2) - 1;
89  dst.x = luaL_checkinteger(L, 3) - 1;
90  dst.y = luaL_checkinteger(L, 4) - 1;
91  if(lua_isfunction(L, arg)) {
92  const char *msg = lua_pushfstring(L, "%s expected, got %s", lua_typename(L, LUA_TFUNCTION), luaL_typename(L, 5));
93  return luaL_argerror(L, 5, msg);
94  }
96  int width = luaL_checkinteger(L, 6);
97  int height = luaL_checkinteger(L, 7);
98  bool border = false;
99  if(lua_isboolean(L, 8)) {
100  border = luaW_toboolean(L, 8);
101  }
102  pathfind::plain_route res = pathfind::a_star_search(src, dst, 10000, &calc, width, height, nullptr, border);
103 
104  int nb = res.steps.size();
105  lua_createtable(L, nb, 0);
106  for (int i = 0; i < nb; ++i)
107  {
108  lua_createtable(L, 2, 0);
109  lua_pushinteger(L, res.steps[i].x + 1);
110  lua_rawseti(L, -2, 1);
111  lua_pushinteger(L, res.steps[i].y + 1);
112  lua_rawseti(L, -2, 2);
113  lua_rawseti(L, -2, i + 1);
114  }
115  lua_pushinteger(L, res.move_cost);
116 
117  return 2;
118 }
119 
120 
122  : lua_kernel_base(nullptr)
123  , random_seed_()
124  , default_rng_()
125 {
126  lua_State *L = mState;
127  lua_settop(L, 0);
128 
129  static luaL_Reg const callbacks[] = {
130  { "find_path", &intf_find_path },
131  { "random", &intf_random },
132  { nullptr, nullptr }
133  };
134 
135  lua_getglobal(L, "wesnoth");
136  assert(lua_istable(L,-1));
137  luaL_setfuncs(L, callbacks, 0);
138  lua_pop(L, 1);
139  assert(lua_gettop(L) == 0);
140 }
141 
142 void mapgen_lua_kernel::run_generator(const char * prog, const config & generator)
143 {
144  load_string(prog, std::bind(&lua_kernel_base::throw_exception, this, _1, _2));
145  luaW_pushconfig(mState, generator);
146  protected_call(1, 1, std::bind(&lua_kernel_base::throw_exception, this, _1, _2));
147 }
148 
149 void mapgen_lua_kernel::user_config(const char * prog, const config & generator)
150 {
151  run_generator(prog, generator);
152 }
153 
154 std::string mapgen_lua_kernel::create_map(const char * prog, const config & generator, boost::optional<boost::uint32_t> seed) // throws game::lua_error
155 {
156  random_seed_ = seed;
157  run_generator(prog, generator);
158 
159  if (!lua_isstring(mState,-1)) {
160  std::string msg = "expected a string, found a ";
161  msg += lua_typename(mState, lua_type(mState, -1));
162  lua_pop(mState, 1);
163  throw game::lua_error(msg.c_str(),"bad return value");
164  }
165 
166  return lua_tostring(mState, -1);
167 }
168 
169 config mapgen_lua_kernel::create_scenario(const char * prog, const config & generator, boost::optional<boost::uint32_t> seed) // throws game::lua_error
170 {
171  random_seed_ = seed;
172  run_generator(prog, generator);
173 
174  if (!lua_istable(mState, -1)) {
175  std::string msg = "expected a config (table), found a ";
176  msg += lua_typename(mState, lua_type(mState, -1));
177  lua_pop(mState, 1);
178  throw game::lua_error(msg.c_str(),"bad return value");
179  }
180  config result;
181  if (!luaW_toconfig(mState, -1, result)) {
182  std::string msg = "expected a config, but it is malformed ";
183  lua_pop(mState, 1);
184  throw game::lua_error(msg.c_str(),"bad return value");
185  }
186  return result;
187 }
189 {
190  if(boost::uint32_t* pint = random_seed_.get_ptr()) {
191  return (*pint)++;
192  }
193  else {
195  }
196 }
197 
199 {
200  if(!default_rng_) {
201  default_rng_ = boost::mt19937(get_random_seed());
202  }
203  return *default_rng_;
204 }
#define lua_isnoneornil(L, n)
Definition: lua.h:337
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
Definition: lapi.cpp:667
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports, bool border)
static int intf_random(lua_State *L)
Returns a random numer, same interface as math.random.
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
Definition: lauxlib.cpp:391
LUA_API void lua_settop(lua_State *L, int idx)
Definition: lapi.cpp:159
boost::optional< boost::mt19937 > default_rng_
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.cpp:243
rng * generator
This generator is automatically synced during synced context.
Definition: random_new.cpp:52
boost::uint32_t uint32_t
Definition: xbrz.hpp:45
LUA_API void lua_getglobal(lua_State *L, const char *var)
Definition: lapi.cpp:602
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.cpp:154
#define luaL_typename(L, i)
Definition: lauxlib.h:122
GLenum src
Definition: glew.h:2392
#define LUA_TFUNCTION
Definition: lua.h:83
void lua_push(lua_State *L, const T &val)
Definition: push_check.hpp:314
Definitions for the interface to Wesnoth Markup Language (WML).
config create_scenario(const char *prog, const config &generator, boost::optional< boost::uint32_t > seed)
#define lua_pop(L, n)
Definition: lua.h:322
virtual boost::uint32_t get_random_seed()
GLuint64EXT * result
Definition: glew.h:10727
std::vector< map_location > steps
Definition: pathfind.hpp:135
LUA_API int lua_isstring(lua_State *L, int idx)
Definition: lapi.cpp:268
bool luaW_toboolean(lua_State *L, int n)
Definition: lua_common.cpp:811
Structure which holds a single route between one location and another.
Definition: pathfind.hpp:132
void user_config(const char *prog, const config &generator)
GLenum GLenum dst
Definition: glew.h:2392
bool protected_call(int nArgs, int nRets, error_handler)
int move_cost
Movement cost for reaching the end of the route.
Definition: pathfind.hpp:137
bool load_string(char const *prog, error_handler)
Encapsulates the map of the game.
Definition: location.hpp:38
#define lua_isboolean(L, n)
Definition: lua.h:334
bool luaW_toconfig(lua_State *L, int index, config &cfg)
Converts an optional table or vconfig to a config object.
Definition: lua_common.cpp:675
GLuint res
Definition: glew.h:9258
Cost function object relying on a Lua function.
#define lua_isfunction(L, n)
Definition: lua.h:330
LUALIB_API int luaL_argerror(lua_State *L, int narg, const char *extramsg)
Definition: lauxlib.cpp:152
size_t i
Definition: function.cpp:1057
#define lua_tostring(L, i)
Definition: lua.h:345
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:112
LUA_API void lua_rawseti(lua_State *L, int idx, int n)
Definition: lapi.cpp:778
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
LUA_API int lua_isnumber(lua_State *L, int idx)
Definition: lapi.cpp:261
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
Definition: glew.h:1220
virtual boost::uint32_t get_random_seed()
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: glew.h:1222
LUA_API int lua_error(lua_State *L)
Definition: lapi.cpp:1099
#define lua_istable(L, n)
Definition: lua.h:331
static int intf_find_path(lua_State *L)
Finds a path between two locations.
virtual void throw_exception(char const *msg, char const *context="Lua error")
void luaW_pushconfig(lua_State *L, config const &cfg)
Converts a config object to a Lua table pushed at the top of the stack.
Definition: lua_common.cpp:663
static lg::log_domain log_mapgen("mapgen")
Standard logging facilities (interface).
LUA_API const char * lua_pushfstring(lua_State *L, const char *fmt,...)
Definition: lapi.cpp:536
GLint GLint GLint GLint GLint GLint GLsizei width
Definition: glew.h:1220
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
Definition: lauxlib.cpp:850
void run_generator(const char *prog, const config &generator)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
lua_State * mState
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.cpp:477
GLsizei const GLcharARB ** string
Definition: glew.h:4503
boost::mt19937 & get_default_rng()
std::string create_map(const char *prog, const config &generator, boost::optional< boost::uint32_t > seed)
LUA_API const char * lua_typename(lua_State *L, int t)
Definition: lapi.cpp:249
boost::optional< boost::uint32_t > random_seed_