Merge pull request #324 from cbeck88/lua_map_generator
Lua map generator
This commit is contained in:
commit
fb793a10ce
17 changed files with 485 additions and 54 deletions
|
@ -5,7 +5,7 @@
|
|||
id=multiplayer_Random_Map
|
||||
name= _ "Random map"
|
||||
description= _ "Randomly generated map. Note: random maps are often unbalanced, but if you have time, you can regenerate them until you get a good one."
|
||||
map_generation=default
|
||||
scenario_generation=default
|
||||
[generator]
|
||||
[scenario]
|
||||
name= _ "Random map"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
id=multiplayer_Random_Map_Desert
|
||||
name= _ "Random map (Desert)"
|
||||
description= _ "A random map with sand as the primary terrain. Note: random maps are often unbalanced, but if you have time, you can regenerate them until you get a good one."
|
||||
map_generation=default
|
||||
scenario_generation=default
|
||||
[generator]
|
||||
[scenario]
|
||||
name= _ "Random map (Desert)"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
id=multiplayer_Random_Map_Marsh
|
||||
name= _ "Random map (Marsh)"
|
||||
description= _ "A random map with swamp as the primary terrain. Note: random maps are often unbalanced, but if you have time, you can regenerate them until you get a good one."
|
||||
map_generation=default
|
||||
scenario_generation=default
|
||||
[generator]
|
||||
[scenario]
|
||||
name= _ "Random map (Marsh)"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
id=multiplayer_Random_Map_Winter
|
||||
name= _ "Random map (Winter)"
|
||||
description= _ "A random map set in the break between spring and winter, mainly with snowy terrains. Note: random maps are often unbalanced, but if you have time, you can regenerate them until you get a good one."
|
||||
map_generation=default
|
||||
scenario_generation=default
|
||||
[generator]
|
||||
[scenario]
|
||||
name= _ "Random map (Winter)"
|
||||
|
|
|
@ -7,24 +7,6 @@
|
|||
description= _ "Randomly generated map. Note: random maps are often unbalanced, but if you have time, you can regenerate them until you get a good one."
|
||||
map_generation=yamg
|
||||
[generator]
|
||||
[scenario]
|
||||
name= _ "Random map"
|
||||
id=multiplayer_Random_Map
|
||||
{DEFAULT_MUSIC_PLAYLIST}
|
||||
{DEFAULT_SCHEDULE}
|
||||
|
||||
[event]
|
||||
name=prestart
|
||||
|
||||
{SCATTER_EMBELLISHMENTS G* ^Efm 7}
|
||||
{SCATTER_EMBELLISHMENTS Re,Rb,Gd ^Gvs 5}
|
||||
{SCATTER_EMBELLISHMENTS G*,D*,R*,Uu*,Ur* ^Es 2}
|
||||
{SCATTER_EMBELLISHMENTS G*,R*,Uu*,Ur* ^Em 2}
|
||||
{SCATTER_EMBELLISHMENTS Uu* ^Emf 2}
|
||||
{SCATTER_EMBELLISHMENTS D* ^Edp 2}
|
||||
{SCATTER_EMBELLISHMENTS G*,R* ^Wm 0.25}
|
||||
[/event]
|
||||
[/scenario]
|
||||
name=default
|
||||
map_width=40
|
||||
map_height=40
|
||||
|
@ -256,4 +238,18 @@
|
|||
[/village_naming]
|
||||
[/generator]
|
||||
#undef MIN_COST_ROAD
|
||||
{DEFAULT_MUSIC_PLAYLIST}
|
||||
{DEFAULT_SCHEDULE}
|
||||
|
||||
[event]
|
||||
name=prestart
|
||||
|
||||
{SCATTER_EMBELLISHMENTS G* ^Efm 7}
|
||||
{SCATTER_EMBELLISHMENTS Re,Rb,Gd ^Gvs 5}
|
||||
{SCATTER_EMBELLISHMENTS G*,D*,R*,Uu*,Ur* ^Es 2}
|
||||
{SCATTER_EMBELLISHMENTS G*,R*,Uu*,Ur* ^Em 2}
|
||||
{SCATTER_EMBELLISHMENTS Uu* ^Emf 2}
|
||||
{SCATTER_EMBELLISHMENTS D* ^Edp 2}
|
||||
{SCATTER_EMBELLISHMENTS G*,R* ^Wm 0.25}
|
||||
[/event]
|
||||
[/multiplayer]
|
||||
|
|
|
@ -1006,6 +1006,7 @@ set(libwesnoth-game_STAT_SRC
|
|||
generators/map_create.cpp
|
||||
generators/map_generator.cpp
|
||||
generators/default_map_generator.cpp
|
||||
generators/lua_map_generator.cpp
|
||||
generators/yamg/ya_mapgen.cpp
|
||||
generators/yamg/yamg_hex.cpp
|
||||
generators/yamg/yamg_hexheap.cpp
|
||||
|
|
|
@ -93,6 +93,7 @@ libwesnoth_sources = Split("""
|
|||
generators/map_create.cpp
|
||||
generators/map_generator.cpp
|
||||
generators/default_map_generator.cpp
|
||||
generators/lua_map_generator.cpp
|
||||
generators/yamg/ya_mapgen.cpp
|
||||
generators/yamg/yamg_hex.cpp
|
||||
generators/yamg/yamg_hexheap.cpp
|
||||
|
|
|
@ -6,15 +6,27 @@
|
|||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
namespace ng {
|
||||
|
||||
static const config dummy;
|
||||
|
||||
configure_engine::configure_engine(saved_game& state) :
|
||||
state_(state),
|
||||
parameters_(state_.mp_settings()),
|
||||
sides_(state_.get_starting_pos().child_range("side")),
|
||||
cfg_((assert(sides_.first != sides_.second), *sides_.first))
|
||||
cfg_(sides_.first != sides_.second ? *sides_.first : dummy) //second part is just any old config, it will be ignored
|
||||
{
|
||||
if (sides_.first == sides_.second) {
|
||||
std::stringstream msg;
|
||||
msg << "Configure Engine: No sides found in scenario, aborting.";
|
||||
std::cerr << msg;
|
||||
std::cerr << "Full scenario config:\n";
|
||||
std::cerr << state_.to_config().debug();
|
||||
throw game::error(msg.str());
|
||||
}
|
||||
|
||||
set_use_map_settings(use_map_settings_default());
|
||||
|
||||
BOOST_FOREACH(const config& scenario,
|
||||
|
|
|
@ -42,6 +42,7 @@ static lg::log_domain log_config("config");
|
|||
#define ERR_CF LOG_STREAM(err, log_config)
|
||||
|
||||
static lg::log_domain log_mp_create_engine("mp/create/engine");
|
||||
#define WRN_MP LOG_STREAM(warn, log_mp_create_engine)
|
||||
#define DBG_MP LOG_STREAM(debug, log_mp_create_engine)
|
||||
|
||||
namespace {
|
||||
|
@ -251,10 +252,27 @@ std::string user_map::id() const
|
|||
return name_;
|
||||
}
|
||||
|
||||
random_map::random_map(const config& generator_data) :
|
||||
scenario(config()),
|
||||
generator_data_(generator_data)
|
||||
random_map::random_map(const config& data) :
|
||||
scenario(data),
|
||||
generator_data_(),
|
||||
generate_whole_scenario_(data_.has_attribute("scenario_generation")),
|
||||
generator_name_(generate_whole_scenario_ ? data_["scenario_generation"] : data_["map_generation"])
|
||||
{
|
||||
if (!data.has_child("generator")) {
|
||||
data_ = config();
|
||||
generator_data_= config();
|
||||
data_["description"] = "Error: Random map found with missing generator information. Scenario should have a [generator] child.";
|
||||
data_["error_message"] = "missing [generator] tag";
|
||||
} else {
|
||||
generator_data_ = data.child("generator");
|
||||
}
|
||||
|
||||
if (!data.has_attribute("scenario_generation") && !data.has_attribute("map_generation")) {
|
||||
data_ = config();
|
||||
generator_data_= config();
|
||||
data_["description"] = "Error: Random map found with missing generator information. Scenario should have a [generator] child.";
|
||||
data_["error_message"] = "couldn't find 'scenario_generation' or 'map_generation' attribute";
|
||||
}
|
||||
}
|
||||
|
||||
random_map::~random_map()
|
||||
|
@ -268,17 +286,32 @@ const config& random_map::generator_data() const
|
|||
|
||||
std::string random_map::name() const
|
||||
{
|
||||
return generator_data_["name"];
|
||||
return data_["name"];
|
||||
}
|
||||
|
||||
std::string random_map::description() const
|
||||
{
|
||||
return generator_data_["description"];
|
||||
return data_["description"];
|
||||
}
|
||||
|
||||
std::string random_map::id() const
|
||||
{
|
||||
return generator_data_["id"];
|
||||
return data_["id"];
|
||||
}
|
||||
|
||||
bool random_map::generate_whole_scenario() const
|
||||
{
|
||||
return generate_whole_scenario_;
|
||||
}
|
||||
|
||||
std::string random_map::generator_name() const
|
||||
{
|
||||
return generator_name_;
|
||||
}
|
||||
|
||||
map_generator * random_map::create_map_generator() const
|
||||
{
|
||||
return ::create_map_generator(generator_name(), generator_data());
|
||||
}
|
||||
|
||||
campaign::campaign(const config& data) :
|
||||
|
@ -427,16 +460,55 @@ void create_engine::init_generated_level_data()
|
|||
{
|
||||
DBG_MP << "initializing generated level data\n";
|
||||
|
||||
config data = generator_->create_scenario();
|
||||
//DBG_MP << "current data:\n";
|
||||
//DBG_MP << current_level().data().debug();
|
||||
|
||||
// Set the scenario to have placing of sides
|
||||
// based on the terrain they prefer
|
||||
data["modify_placing"] = "true";
|
||||
random_map * cur_lev = dynamic_cast<random_map *> (¤t_level());
|
||||
|
||||
const std::string& description = current_level().data()["description"];
|
||||
data["description"] = description;
|
||||
if (!cur_lev) {
|
||||
WRN_MP << "Tried to initialized generated level data on a level that wasn't a random map\n";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!cur_lev->generate_whole_scenario())
|
||||
{
|
||||
DBG_MP << "** replacing map ** \n";
|
||||
|
||||
config data = cur_lev->data();
|
||||
|
||||
data["map_data"] = generator_->create_map();
|
||||
|
||||
cur_lev->set_data(data);
|
||||
|
||||
} else { //scenario generation
|
||||
|
||||
DBG_MP << "** replacing scenario ** \n";
|
||||
|
||||
config data = generator_->create_scenario();
|
||||
|
||||
// Set the scenario to have placing of sides
|
||||
// based on the terrain they prefer
|
||||
if (!data.has_attribute("modify_placing")) {
|
||||
data["modify_placing"] = "true";
|
||||
}
|
||||
|
||||
const std::string& description = cur_lev->data()["description"];
|
||||
data["description"] = description;
|
||||
|
||||
cur_lev->set_data(data);
|
||||
}
|
||||
} catch (mapgen_exception & e) {
|
||||
config data = cur_lev->data();
|
||||
|
||||
data["error_message"] = e.what();
|
||||
|
||||
cur_lev->set_data(data);
|
||||
}
|
||||
|
||||
//DBG_MP << "final data:\n";
|
||||
//DBG_MP << current_level().data().debug();
|
||||
|
||||
current_level().set_data(data);
|
||||
}
|
||||
|
||||
void create_engine::prepare_for_new_level()
|
||||
|
@ -579,6 +651,7 @@ void create_engine::prepare_for_saved_game()
|
|||
|
||||
void create_engine::prepare_for_other()
|
||||
{
|
||||
DBG_MP << "prepare_for_other\n";
|
||||
state_.set_scenario(current_level().data());
|
||||
state_.mp_settings().hash = current_level().data().hash();
|
||||
}
|
||||
|
@ -735,9 +808,7 @@ void create_engine::set_current_level(const size_t index)
|
|||
random_map* current_random_map =
|
||||
dynamic_cast<random_map*>(¤t_level());
|
||||
|
||||
generator_.reset(create_map_generator(
|
||||
current_random_map->generator_data()["map_generation"],
|
||||
current_random_map->generator_data().child("generator")));
|
||||
generator_.reset(current_random_map->create_map_generator());
|
||||
} else {
|
||||
generator_.reset(NULL);
|
||||
}
|
||||
|
@ -998,7 +1069,7 @@ void create_engine::init_all_levels()
|
|||
if (!data["allow_new_game"].to_bool(true))
|
||||
continue;
|
||||
|
||||
if (!data["map_generation"].empty()) {
|
||||
if (data.has_attribute("map_generation") || data.has_attribute("scenario_generation")) {
|
||||
random_map_ptr new_random_map(new random_map(data));
|
||||
random_maps_.push_back(new_random_map);
|
||||
random_maps_.back()->set_metadata();
|
||||
|
|
|
@ -108,7 +108,7 @@ private:
|
|||
class random_map : public scenario
|
||||
{
|
||||
public:
|
||||
random_map(const config& generator_data);
|
||||
random_map(const config& data);
|
||||
virtual ~random_map();
|
||||
|
||||
const config& generator_data() const;
|
||||
|
@ -116,12 +116,20 @@ public:
|
|||
std::string name() const;
|
||||
std::string description() const;
|
||||
std::string id() const;
|
||||
std::string generator_name() const;
|
||||
|
||||
map_generator * create_map_generator() const;
|
||||
|
||||
bool generate_whole_scenario() const;
|
||||
|
||||
private:
|
||||
random_map(const random_map&);
|
||||
void operator=(const random_map&);
|
||||
|
||||
config generator_data_;
|
||||
|
||||
bool generate_whole_scenario_;
|
||||
std::string generator_name_;
|
||||
};
|
||||
|
||||
class campaign : public level
|
||||
|
|
|
@ -594,11 +594,16 @@ static bool enter_configure_mode(game_display& disp, const config& game_config,
|
|||
mp::ui::result res;
|
||||
|
||||
{
|
||||
mp::configure ui(disp, game_config, gamechat, gamelist, state,
|
||||
local_players_only);
|
||||
run_lobby_loop(disp, ui);
|
||||
res = ui.get_result();
|
||||
ui.get_parameters();
|
||||
if (!state.get_starting_pos().child("side")) {
|
||||
gui2::show_error_message(disp.video(), "No sides found", "This map doesn't have any sides, you can't configure it, skipping...");
|
||||
res = mp::ui::CREATE;
|
||||
} else {
|
||||
mp::configure ui(disp, game_config, gamechat, gamelist, state,
|
||||
local_players_only);
|
||||
run_lobby_loop(disp, ui);
|
||||
res = ui.get_result();
|
||||
ui.get_parameters();
|
||||
}
|
||||
}
|
||||
|
||||
switch (res) {
|
||||
|
|
272
src/generators/lua_map_generator.cpp
Normal file
272
src/generators/lua_map_generator.cpp
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#include "lua_map_generator.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
#include "lua/lauxlib.h"
|
||||
#include "lua/lua.h"
|
||||
#include "lua/lualib.h"
|
||||
|
||||
#include "mt_rng.hpp"
|
||||
|
||||
#ifdef DEBUG_LUA
|
||||
#include "scripting/debug_lua.hpp"
|
||||
#endif
|
||||
|
||||
#include "scripting/lua_api.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
static lg::log_domain log_mapgen("mapgen");
|
||||
#define ERR_NG LOG_STREAM(err, log_mapgen)
|
||||
#define LOG_NG LOG_STREAM(info, log_mapgen)
|
||||
#define DBG_NG LOG_STREAM(debug, log_mapgen)
|
||||
|
||||
// Add compiler directive suppressing unused variable warning
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__MINGW32__)
|
||||
#define ATTR_UNUSED( x ) __attribute__((unused)) x
|
||||
#else
|
||||
#define ATTR_UNUSED( x ) x
|
||||
#endif
|
||||
|
||||
// Begin lua rng bindings
|
||||
|
||||
using rand_rng::mt_rng;
|
||||
|
||||
static const char * Rng = "Rng";
|
||||
|
||||
static int impl_rng_create(lua_State* L);
|
||||
static int impl_rng_destroy(lua_State* L);
|
||||
static int impl_rng_seed(lua_State* L);
|
||||
static int impl_rng_draw(lua_State* L);
|
||||
|
||||
static void initialize_lua_state(lua_State * L)
|
||||
{
|
||||
// Open safe libraries.
|
||||
// Debug and OS are not, but most of their functions will be disabled below.
|
||||
static const luaL_Reg safe_libs[] = {
|
||||
{ "", luaopen_base },
|
||||
{ "table", luaopen_table },
|
||||
{ "string", luaopen_string },
|
||||
{ "math", luaopen_math },
|
||||
{ "debug", luaopen_debug },
|
||||
{ "os", luaopen_os },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
for (luaL_Reg const *lib = safe_libs; lib->func; ++lib)
|
||||
{
|
||||
luaL_requiref(L, lib->name, lib->func, 1);
|
||||
lua_pop(L, 1); /* remove lib */
|
||||
}
|
||||
|
||||
// Disable functions from os which we don't want.
|
||||
lua_getglobal(L, "os");
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -2) != 0) {
|
||||
lua_pop(L, 1);
|
||||
char const* function = lua_tostring(L, -1);
|
||||
if(strcmp(function, "clock") == 0 || strcmp(function, "date") == 0
|
||||
|| strcmp(function, "time") == 0 || strcmp(function, "difftime") == 0) continue;
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, -3, function);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Disable functions from debug which we don't want.
|
||||
lua_getglobal(L, "debug");
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -2) != 0) {
|
||||
lua_pop(L, 1);
|
||||
char const* function = lua_tostring(L, -1);
|
||||
if(strcmp(function, "traceback") == 0) continue;
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, -3, function);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_settop(L, 0);
|
||||
|
||||
// Add mersenne twister rng wrapper
|
||||
|
||||
luaL_newmetatable(L, Rng);
|
||||
|
||||
static luaL_Reg const callbacks[] = {
|
||||
{ "create", &impl_rng_create},
|
||||
{ "__gc", &impl_rng_destroy},
|
||||
{ "seed", &impl_rng_seed},
|
||||
{ "draw", &impl_rng_draw},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
luaL_setfuncs(L, callbacks, 0);
|
||||
|
||||
lua_pushvalue(L, -1); //make a copy of this table, set it to be its own __index table
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_setglobal(L, Rng);
|
||||
}
|
||||
|
||||
int impl_rng_create(lua_State* L)
|
||||
{
|
||||
mt_rng * ATTR_UNUSED(rng) = new ( lua_newuserdata(L, sizeof(mt_rng)) ) mt_rng();
|
||||
luaL_setmetatable(L, Rng);
|
||||
|
||||
return 1;
|
||||
}
|
||||
int impl_rng_destroy(lua_State* L)
|
||||
{
|
||||
mt_rng * d = static_cast< mt_rng *> (luaL_testudata(L, 1, Rng));
|
||||
if (d == NULL) {
|
||||
ERR_NG << "rng_destroy called on data of type: " << lua_typename( L, lua_type( L, 1 ) ) << std::endl;
|
||||
ERR_NG << "This may indicate a memory leak, please report at bugs.wesnoth.org" << std::endl;
|
||||
} else {
|
||||
d->~mt_rng();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int impl_rng_seed(lua_State* L)
|
||||
{
|
||||
mt_rng * rng = static_cast<mt_rng *>(luaL_checkudata(L, 1, Rng));
|
||||
std::string seed = luaL_checkstring(L, 2);
|
||||
|
||||
rng->seed_random(seed);
|
||||
return 0;
|
||||
}
|
||||
int impl_rng_draw(lua_State* L)
|
||||
{
|
||||
mt_rng * rng = static_cast<mt_rng *>(luaL_checkudata(L, 1, Rng));
|
||||
|
||||
lua_pushnumber(L, rng->get_next_random());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// End Lua Rng bindings
|
||||
|
||||
lua_map_generator::lua_map_generator(const config & cfg)
|
||||
: id_(cfg["id"])
|
||||
, config_name_(cfg["config_name"])
|
||||
, create_map_(cfg["create_map"])
|
||||
, create_scenario_(cfg["create_scenario"])
|
||||
, mState_(luaL_newstate())
|
||||
, generator_data_(cfg)
|
||||
{
|
||||
const char* required[] = {"id", "config_name", "create_map"};
|
||||
BOOST_FOREACH(std::string req, required) {
|
||||
if (!cfg.has_attribute(req)) {
|
||||
std::string msg = "Error when constructing a lua map generator -- missing a required attribute '";
|
||||
msg += req + "'\n";
|
||||
msg += "Config was '" + cfg.debug() + "'";
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
}
|
||||
|
||||
initialize_lua_state(mState_);
|
||||
}
|
||||
|
||||
lua_map_generator::~lua_map_generator()
|
||||
{
|
||||
lua_close(mState_);
|
||||
}
|
||||
|
||||
std::string lua_map_generator::create_map()
|
||||
{
|
||||
{
|
||||
int errcode = luaL_loadstring(mState_, create_map_.c_str());
|
||||
if (errcode != LUA_OK) {
|
||||
std::string msg = "Error when running lua_map_generator create_map.\n";
|
||||
msg += "The generator was: " + config_name_ + "\n";
|
||||
msg += "Error when parsing create_map function. ";
|
||||
if (errcode == LUA_ERRSYNTAX) {
|
||||
msg += "There was a syntax error:\n";
|
||||
} else {
|
||||
msg += "There was a memory error:\n";
|
||||
}
|
||||
msg += lua_tostring(mState_, -1);
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
}
|
||||
{
|
||||
luaW_pushconfig(mState_, generator_data_);
|
||||
int errcode = lua_pcall(mState_, 1, 1, 0);
|
||||
if (errcode != LUA_OK) {
|
||||
std::string msg = "Error when running lua_map_generator create_map.\n";
|
||||
msg += "The generator was: " + config_name_ + "\n";
|
||||
msg += "Error when running create_map function. ";
|
||||
if (errcode == LUA_ERRRUN) {
|
||||
msg += "There was a runtime error:\n";
|
||||
} else if (errcode == LUA_ERRERR) {
|
||||
msg += "There was an error with the attached debugger:\n";
|
||||
} else {
|
||||
msg += "There was a memory or garbage collection error:\n";
|
||||
}
|
||||
msg += lua_tostring(mState_, -1);
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
}
|
||||
if (!lua_isstring(mState_,-1)) {
|
||||
std::string msg = "Error when running lua_map_generator create_map.\n";
|
||||
msg += "The generator was: " + config_name_ + "\n";
|
||||
msg += "create_map did not return a string, instead it returned '";
|
||||
msg += lua_typename(mState_, lua_type(mState_, -1));
|
||||
msg += "'";
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
return lua_tostring(mState_, -1);
|
||||
}
|
||||
|
||||
config lua_map_generator::create_scenario()
|
||||
{
|
||||
if (!create_scenario_.size()) {
|
||||
return map_generator::create_scenario();
|
||||
}
|
||||
|
||||
{
|
||||
int errcode = luaL_loadstring(mState_, create_scenario_.c_str());
|
||||
if (errcode != LUA_OK) {
|
||||
std::string msg = "Error when running lua_map_generator create_scenario.\n";
|
||||
msg += "The generator was: " + config_name_ + "\n";
|
||||
msg += "Error when parsing create_scenario function. ";
|
||||
if (errcode == LUA_ERRSYNTAX) {
|
||||
msg += "There was a syntax error:\n";
|
||||
} else {
|
||||
msg += "There was a memory error:\n";
|
||||
}
|
||||
msg += lua_tostring(mState_, -1);
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
}
|
||||
{
|
||||
luaW_pushconfig(mState_, generator_data_);
|
||||
int errcode = lua_pcall(mState_, 1, 1, 0);
|
||||
if (errcode != LUA_OK) {
|
||||
std::string msg = "Error when running lua_map_generator create_scenario.\n";
|
||||
msg += "The generator was: " + config_name_ + "\n";
|
||||
msg += "Error when running create_scenario function. ";
|
||||
if (errcode == LUA_ERRRUN) {
|
||||
msg += "There was a runtime error:\n";
|
||||
} else if (errcode == LUA_ERRERR) {
|
||||
msg += "There was an error with the attached debugger:\n";
|
||||
} else {
|
||||
msg += "There was a memory or garbage collection error:\n";
|
||||
}
|
||||
msg += lua_tostring(mState_, -1);
|
||||
throw mapgen_exception(msg);
|
||||
}
|
||||
}
|
||||
return luaW_checkconfig(mState_, -1);
|
||||
}
|
57
src/generators/lua_map_generator.hpp
Normal file
57
src/generators/lua_map_generator.hpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright (C) 2014 by Chris Beck <render787@gmail.com>
|
||||
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#ifndef LUA_MAP_GENERATOR_DEFINED
|
||||
#define LUA_MAP_GENERATOR_DEFINED
|
||||
|
||||
#include "config.hpp"
|
||||
#include "map_generator.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
// TODO: Add support for user configurability (via defining a gui2 dialog in lua)
|
||||
// What's missing is that you need access to the 'wesnoth' object to call show dialog
|
||||
// at the moment.
|
||||
|
||||
class lua_map_generator : public map_generator {
|
||||
public:
|
||||
lua_map_generator(const config & cfg);
|
||||
|
||||
~lua_map_generator();
|
||||
|
||||
bool allow_user_config() const { return false; }
|
||||
|
||||
std::string name() const { return "lua"; }
|
||||
|
||||
std::string id() const { return id_; }
|
||||
|
||||
std::string config_name() const { return config_name_; }
|
||||
|
||||
virtual std::string create_map();
|
||||
virtual config create_scenario();
|
||||
|
||||
private:
|
||||
std::string id_, config_name_;
|
||||
|
||||
std::string create_map_;
|
||||
std::string create_scenario_;
|
||||
|
||||
lua_State * mState_;
|
||||
|
||||
config generator_data_;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -18,11 +18,13 @@
|
|||
#include "generators/cave_map_generator.hpp"
|
||||
#include "generators/yamg/ya_mapgen.hpp"
|
||||
#include "generators/default_map_generator.hpp"
|
||||
#include "generators/lua_map_generator.hpp"
|
||||
#include "log.hpp"
|
||||
#include "scoped_resource.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
|
||||
static lg::log_domain log_config("config");
|
||||
#define ERR_CF LOG_STREAM(err, log_config)
|
||||
|
@ -35,6 +37,8 @@ map_generator* create_map_generator(const std::string& name, const config &cfg)
|
|||
return new cave_map_generator(cfg);
|
||||
} else if(name == "yamg") {
|
||||
return new ya_mapgen(cfg);
|
||||
} else if(name == "lua") {
|
||||
return new lua_map_generator(cfg);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -50,8 +54,9 @@ std::string random_generate_map(const std::string& parms, const config &cfg)
|
|||
assert(!parameters.empty()); //we use parameters.front() in the next line.
|
||||
util::scoped_ptr<map_generator> generator(create_map_generator(parameters.front(),cfg));
|
||||
if(generator == NULL) {
|
||||
ERR_CF << "could not find map generator '" << parameters.front() << "'" << std::endl;
|
||||
return std::string();
|
||||
std::stringstream ss;
|
||||
ss << "could not find map generator '" << parameters.front() << "'";
|
||||
throw mapgen_exception(ss.str());
|
||||
}
|
||||
|
||||
parameters.erase(parameters.begin());
|
||||
|
@ -66,8 +71,9 @@ config random_generate_scenario(const std::string& parms, const config &cfg)
|
|||
assert(!parameters.empty()); //we use parameters.front() in the next line.
|
||||
util::scoped_ptr<map_generator> generator(create_map_generator(parameters.front(),cfg));
|
||||
if(generator == NULL) {
|
||||
ERR_CF << "could not find map generator '" << parameters.front() << "'" << std::endl;
|
||||
return config();
|
||||
std::stringstream ss;
|
||||
ss << "could not find map generator '" << parameters.front() << "'";
|
||||
throw mapgen_exception(ss.str());
|
||||
}
|
||||
|
||||
parameters.erase(parameters.begin());
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
static lg::log_domain log_engine("engine");
|
||||
#define ERR_NG LOG_STREAM(err, log_engine)
|
||||
#define LOG_NG LOG_STREAM(info, log_engine)
|
||||
static lg::log_domain log_mapgen("mapgen");
|
||||
#define ERR_NG LOG_STREAM(err, log_mapgen)
|
||||
#define LOG_NG LOG_STREAM(info, log_mapgen)
|
||||
|
||||
config map_generator::create_scenario()
|
||||
{
|
||||
|
|
|
@ -820,7 +820,7 @@ struct twrapper<gui2::teditor_generate_map>
|
|||
|
||||
std::vector<map_generator*> map_generators;
|
||||
BOOST_FOREACH(const config &i, main_config.child_range("multiplayer")) {
|
||||
if(i["map_generation"] == "default") {
|
||||
if(i["scenario_generation"] == "default") {
|
||||
const config &generator_cfg = i.child("generator");
|
||||
if (generator_cfg) {
|
||||
map_generators.push_back(
|
||||
|
|
|
@ -86,6 +86,8 @@
|
|||
#include "SDL_stdinc.h" // for SDL_putenv, Uint32
|
||||
#include "SDL_timer.h" // for SDL_GetTicks
|
||||
|
||||
//#define NO_CATCH_AT_GAME_END
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue