Add new aspect 'advancements'
As part of a GSoC proposal I added a new aspect so a scenario editor can control advancements in two ways: 1. Define a aspect with a string-value like "Swordsman, Knight", so the units of interesst will always advance to this 2. Use the LUA-Engine and return a function of the form advance(x, y) which will itself return a string-value like "Swordsman, Knight". Everytime a ai-unit advances advance(x, y) will be called. The corresponding wikipage (http://wiki.wesnoth.org/AiWML) is going to be updated soon.
This commit is contained in:
parent
f9a231f09d
commit
29e8584738
21 changed files with 374 additions and 17 deletions
|
@ -22,6 +22,10 @@ Version 1.11.4+dev:
|
|||
* Added a new playlist FULL_MUSIC_PLAYLIST, which contains all Wesnoth tracks
|
||||
in alphabetical order
|
||||
* Added -Wno-null-conversion to the CMake pedantic flags.
|
||||
* WML engine:
|
||||
* Added new aspect 'advancements' which with lua engine can handle a
|
||||
function return type of the form f(x, y) -> String. 'advancements'
|
||||
tells the AI to what unit a given unit should advance to.
|
||||
|
||||
Version 1.11.4:
|
||||
* AI:
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
[/aspect]
|
||||
#enddef
|
||||
|
||||
{DEFAULT_ASPECT_EMPTY advancements}
|
||||
{DEFAULT_ASPECT_VALUE aggression 0.4}
|
||||
{DEFAULT_ASPECT_VALUE attack_depth 5}
|
||||
[aspect]
|
||||
|
|
|
@ -989,6 +989,9 @@
|
|||
[entry]
|
||||
name = "Fedor Khod'kov (teddy/fkhodkov)"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Felix Bauer (flix)"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Francesco Gigli (Jaramir)"
|
||||
[/entry]
|
||||
|
|
|
@ -864,7 +864,7 @@ def local_sanity_check(filename, nav, key, prefix, value, comment):
|
|||
"recruitment_ignore_bad_combat",
|
||||
"recruitment_pattern",
|
||||
"villages_per_scout", "leader_value", "village_value",
|
||||
"aggression", "caution", "attack_depth", "grouping"):
|
||||
"aggression", "caution", "attack_depth", "grouping", "advancements"):
|
||||
print errlead + key + " outside [ai] scope"
|
||||
# Bad [recruit] attribute
|
||||
if parent in ("[allow_recruit]", "[disallow_recruit]") and key == "recruit":
|
||||
|
|
|
@ -3050,6 +3050,62 @@
|
|||
RelativePath="..\..\src\ai\lua\lua_object.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\lua\unit_advancements_aspect.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug_with_VLD|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Test_Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Test_Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="ReleaseDEBUG|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)\ai\lua\"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\ai\lua\unit_advancements_aspect.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="akihara"
|
||||
|
|
|
@ -631,6 +631,7 @@ set(wesnoth-main_SRC
|
|||
ai/interface.cpp
|
||||
ai/lua/core.cpp
|
||||
ai/lua/lua_object.cpp
|
||||
ai/lua/unit_advancements_aspect.cpp
|
||||
ai/manager.cpp
|
||||
ai/registry.cpp
|
||||
ai/testing.cpp
|
||||
|
|
|
@ -203,6 +203,7 @@ wesnoth_sources = Split("""
|
|||
ai/interface.cpp
|
||||
ai/lua/core.cpp
|
||||
ai/lua/lua_object.cpp
|
||||
ai/lua/unit_advancements_aspect.cpp
|
||||
ai/manager.cpp
|
||||
ai/registry.cpp
|
||||
ai/testing.cpp
|
||||
|
|
|
@ -179,8 +179,8 @@ team& action_result::get_my_team() const
|
|||
|
||||
|
||||
// attack_result
|
||||
attack_result::attack_result( side_number side, const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon, double aggression)
|
||||
: action_result(side), attacker_loc_(attacker_loc), defender_loc_(defender_loc), attacker_weapon_(attacker_weapon), aggression_(aggression){
|
||||
attack_result::attack_result( side_number side, const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon, double aggression, const unit_advancements_aspect& advancements)
|
||||
: action_result(side), attacker_loc_(attacker_loc), defender_loc_(defender_loc), attacker_weapon_(attacker_weapon), aggression_(aggression), advancements_(advancements){
|
||||
}
|
||||
|
||||
|
||||
|
@ -302,7 +302,8 @@ void attack_result::do_execute()
|
|||
}
|
||||
recorder.add_seed("attack", rand_rng::get_last_seed());
|
||||
attack_unit(attacker_loc_, defender_loc_, attacker_weapon, defender_weapon);
|
||||
dialogs::advance_unit(attacker_loc_, true);
|
||||
|
||||
dialogs::advance_unit(attacker_loc_, true, false, advancements_);
|
||||
|
||||
const unit_map::const_iterator defender = resources::units->find(defender_loc_);
|
||||
if(defender != resources::units->end()) {
|
||||
|
@ -922,9 +923,10 @@ attack_result_ptr actions::execute_attack_action( side_number side,
|
|||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon,
|
||||
double aggression)
|
||||
double aggression,
|
||||
const unit_advancements_aspect& advancements)
|
||||
{
|
||||
attack_result_ptr action(new attack_result(side,attacker_loc,defender_loc,attacker_weapon,aggression));
|
||||
attack_result_ptr action(new attack_result(side,attacker_loc,defender_loc,attacker_weapon,aggression,advancements));
|
||||
execute ? action->execute() : action->check_before();
|
||||
return action;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "game_info.hpp"
|
||||
|
||||
#include "../actions/move.hpp"
|
||||
#include "lua/unit_advancements_aspect.hpp"
|
||||
|
||||
namespace pathfind {
|
||||
struct plain_route;
|
||||
|
@ -130,7 +131,8 @@ public:
|
|||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon,
|
||||
double aggression );
|
||||
double aggression,
|
||||
const unit_advancements_aspect& advancements = unit_advancements_aspect());
|
||||
|
||||
enum tresult {
|
||||
E_EMPTY_ATTACKER = 1001,
|
||||
|
@ -156,6 +158,7 @@ private:
|
|||
const map_location& defender_loc_;
|
||||
int attacker_weapon_;
|
||||
double aggression_;
|
||||
const unit_advancements_aspect& advancements_;
|
||||
};
|
||||
|
||||
class move_result : public action_result {
|
||||
|
@ -314,7 +317,8 @@ static attack_result_ptr execute_attack_action( side_number side,
|
|||
const map_location& attacker_loc,
|
||||
const map_location& defender_loc,
|
||||
int attacker_weapon,
|
||||
double aggression );
|
||||
double aggression,
|
||||
const unit_advancements_aspect& advancements = unit_advancements_aspect());
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "../../util.hpp"
|
||||
#include "../../serialization/string_utils.hpp"
|
||||
#include "../../resources.hpp"
|
||||
#include "../lua/unit_advancements_aspect.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
|
@ -202,6 +203,35 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class config_value_translator<unit_advancements_aspect> {
|
||||
public:
|
||||
|
||||
static unit_advancements_aspect cfg_to_value(const config &cfg)
|
||||
{
|
||||
return unit_advancements_aspect(cfg["value"]);
|
||||
}
|
||||
|
||||
static void cfg_to_value(const config &cfg, unit_advancements_aspect &value)
|
||||
{
|
||||
value = cfg_to_value(cfg);
|
||||
}
|
||||
|
||||
static void value_to_cfg(const unit_advancements_aspect &value, config &cfg)
|
||||
{
|
||||
cfg["value"] = value.get_value();
|
||||
|
||||
}
|
||||
|
||||
static config value_to_cfg(const unit_advancements_aspect &value)
|
||||
{
|
||||
config cfg;
|
||||
value_to_cfg(value,cfg);
|
||||
return cfg;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// variant value translator
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ void configuration::init(const config &game_config)
|
|||
ai_configurations_.clear();
|
||||
era_ai_configurations_.clear();
|
||||
well_known_aspects.clear();
|
||||
well_known_aspects.push_back(well_known_aspect("advancements"));
|
||||
well_known_aspects.push_back(well_known_aspect("aggression"));
|
||||
well_known_aspects.push_back(well_known_aspect("attack_depth"));
|
||||
well_known_aspects.push_back(well_known_aspect("attacks"));
|
||||
|
|
|
@ -90,14 +90,16 @@ team& readwrite_context_impl::current_team_w()
|
|||
attack_result_ptr readwrite_context_impl::execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
|
||||
unit_map::iterator i = resources::units->find(attacker_loc);
|
||||
double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
|
||||
return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon, m_aggression);
|
||||
const unit_advancements_aspect& m_advancements = get_advancements();
|
||||
return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon, m_aggression, m_advancements);
|
||||
}
|
||||
|
||||
|
||||
attack_result_ptr readonly_context_impl::check_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
|
||||
unit_map::iterator i = resources::units->find(attacker_loc);
|
||||
double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
|
||||
return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon, m_aggression);
|
||||
const unit_advancements_aspect& m_advancements = get_advancements();
|
||||
return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon, m_aggression, m_advancements);
|
||||
}
|
||||
|
||||
|
||||
|
@ -152,6 +154,7 @@ readonly_context_impl::readonly_context_impl(side_context &context, const config
|
|||
: cfg_(cfg),
|
||||
engines_(),
|
||||
known_aspects_(),
|
||||
advancements_(),
|
||||
aggression_(),
|
||||
attack_depth_(),
|
||||
aspects_(),
|
||||
|
@ -195,6 +198,7 @@ readonly_context_impl::readonly_context_impl(side_context &context, const config
|
|||
init_side_context_proxy(context);
|
||||
manager::add_gamestate_observer(this);
|
||||
|
||||
add_known_aspect("advancements", advancements_);
|
||||
add_known_aspect("aggression",aggression_);
|
||||
add_known_aspect("attack_depth",attack_depth_);
|
||||
add_known_aspect("attacks",attacks_);
|
||||
|
@ -491,6 +495,17 @@ std::map<map_location,defensive_position>& readonly_context_impl::defensive_posi
|
|||
}
|
||||
|
||||
|
||||
const unit_advancements_aspect& readonly_context_impl::get_advancements() const
|
||||
{
|
||||
if (advancements_) {
|
||||
return advancements_->get();
|
||||
}
|
||||
|
||||
static unit_advancements_aspect uaa = unit_advancements_aspect();
|
||||
return uaa;
|
||||
}
|
||||
|
||||
|
||||
double readonly_context_impl::get_aggression() const
|
||||
{
|
||||
if (aggression_) {
|
||||
|
@ -842,6 +857,7 @@ int readonly_context_impl::get_villages_per_scout() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool readonly_context_impl::is_dst_src_valid_lua() const
|
||||
{
|
||||
return dst_src_valid_lua_;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "game_info.hpp"
|
||||
#include "../generic_event.hpp"
|
||||
#include "../config.hpp"
|
||||
#include "lua/unit_advancements_aspect.hpp"
|
||||
|
||||
|
||||
//#include "../unit.hpp"
|
||||
|
@ -207,6 +208,9 @@ public:
|
|||
virtual std::map<map_location,defensive_position>& defensive_position_cache() const = 0;
|
||||
|
||||
|
||||
virtual const unit_advancements_aspect& get_advancements() const = 0;
|
||||
|
||||
|
||||
virtual double get_aggression() const = 0;
|
||||
|
||||
|
||||
|
@ -326,6 +330,7 @@ public:
|
|||
virtual int get_villages_per_scout() const = 0;
|
||||
|
||||
|
||||
|
||||
virtual bool is_active(const std::string &time_of_day, const std::string &turns) const = 0;
|
||||
|
||||
virtual bool is_dst_src_valid_lua() const = 0;
|
||||
|
@ -607,6 +612,12 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual const unit_advancements_aspect& get_advancements() const
|
||||
{
|
||||
return target_->get_advancements();
|
||||
}
|
||||
|
||||
|
||||
virtual double get_aggression() const
|
||||
{
|
||||
return target_->get_aggression();
|
||||
|
@ -1264,6 +1275,9 @@ public:
|
|||
virtual std::map<map_location,defensive_position>& defensive_position_cache() const;
|
||||
|
||||
|
||||
virtual const unit_advancements_aspect& get_advancements() const;
|
||||
|
||||
|
||||
virtual double get_aggression() const;
|
||||
|
||||
|
||||
|
@ -1449,6 +1463,7 @@ private:
|
|||
|
||||
known_aspect_map known_aspects_;
|
||||
|
||||
aspect_type< unit_advancements_aspect >::typesafe_ptr advancements_;
|
||||
aspect_type<double>::typesafe_ptr aggression_;
|
||||
aspect_type<int>::typesafe_ptr attack_depth_;
|
||||
aspect_map aspects_;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "../default/contexts.hpp"
|
||||
#include "terrain_filter.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "unit_advancements_aspect.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
|
@ -190,6 +191,12 @@ inline boost::shared_ptr<std::vector<target> > lua_object< std::vector<target> >
|
|||
return targets;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline boost::shared_ptr<unit_advancements_aspect> lua_object<unit_advancements_aspect>::to_type(lua_State *L, int n)
|
||||
{
|
||||
boost::shared_ptr<unit_advancements_aspect> uaa = boost::shared_ptr<unit_advancements_aspect>(new unit_advancements_aspect(L, n));
|
||||
return uaa;
|
||||
}
|
||||
} // end of namespace ai
|
||||
|
||||
|
||||
|
|
130
src/ai/lua/unit_advancements_aspect.cpp
Normal file
130
src/ai/lua/unit_advancements_aspect.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
Copyright (C) 2013 by Felix Bauer <fehlxb+wesnoth@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 "unit_advancements_aspect.hpp"
|
||||
#include "../../log.hpp"
|
||||
#include "lua/lualib.h"
|
||||
#include "lua/lauxlib.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "scripting/lua.hpp"
|
||||
#include "scripting/lua_api.hpp"
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "../../unit.hpp"
|
||||
#include "../../map.hpp"
|
||||
|
||||
|
||||
static lg::log_domain log_ai_engine_lua("ai/engine/lua");
|
||||
#define LOG_LUA LOG_STREAM(info, log_ai_engine_lua)
|
||||
#define ERR_LUA LOG_STREAM(err, log_ai_engine_lua)
|
||||
|
||||
namespace ai{
|
||||
|
||||
unit_advancements_aspect::unit_advancements_aspect():
|
||||
val_(), L_(),ref_()
|
||||
{
|
||||
}
|
||||
|
||||
unit_advancements_aspect::unit_advancements_aspect(lua_State* L, int n)
|
||||
{
|
||||
val_ = "Lua Function";
|
||||
L_ = L;
|
||||
lua_settop(L, n);
|
||||
|
||||
//on the top of the Lua-Stack is now the pointer to the function. Save it:
|
||||
ref_ = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
}
|
||||
|
||||
unit_advancements_aspect::unit_advancements_aspect(const std::string& val): val_(val), L_(), ref_()
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<std::string> unit_advancements_aspect::get_advancements(const unit_map::const_iterator& unit) const
|
||||
{
|
||||
|
||||
|
||||
if(!unit.valid())
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
const std::string& unit_id = (*unit).id();
|
||||
const int unit_x = (*unit).get_location().x + 1;
|
||||
const int unit_y = (*unit).get_location().y + 1;
|
||||
|
||||
LOG_LUA << "Entering unit_advancements_aspect::get_advancements() in instance " << this << " with unit " << unit_id << " on (x,y) = (" << unit_x << ", " << unit_y << ")\n";
|
||||
|
||||
if(L_ == NULL || ref_ == LUA_REFNIL)
|
||||
{
|
||||
//If we end up here, most likely the aspect don't use the lua-engine.
|
||||
//Just to make sure:
|
||||
if (val_ == "Lua Function")
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
return utils::split(val_);
|
||||
}
|
||||
|
||||
//put the Pointer back on the Stack
|
||||
lua_rawgeti(L_, LUA_REGISTRYINDEX, ref_);
|
||||
|
||||
if(lua_isstring(L_, -1))
|
||||
{
|
||||
return utils::split(lua_tostring(L_, -1));
|
||||
}
|
||||
|
||||
if(!lua_isfunction(L_, -1))
|
||||
{
|
||||
ERR_LUA << "Can't evaluate advancement aspect: Value is neither a string nor a function.\n";
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
//push parameter to the stack
|
||||
lua_pushinteger(L_, unit_x);
|
||||
lua_pushinteger(L_, unit_y);
|
||||
|
||||
//To make unit_id a Parameter of the Lua function:
|
||||
//lua_pushfstring(L_, unit_id.c_str());
|
||||
|
||||
//call function
|
||||
if(lua_pcall(L_, 2, 1, 0) != 0)
|
||||
{
|
||||
ERR_LUA << "LUA Error while evaluating advancements_aspect: " << lua_tostring(L_, -1) << "\n";
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
if (!lua_isstring(L_, -1))
|
||||
{
|
||||
ERR_LUA << "LUA Error while evaluating advancements_aspect: Function must return String \n";
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
//get result from Lua-Stack
|
||||
const std::string retval = std::string(lua_tostring(L_, -1));
|
||||
lua_pop(L_, 1);
|
||||
|
||||
LOG_LUA << "Called Lua advancement function. Result was: \"" << retval << "\".\n";
|
||||
|
||||
return utils::split(retval);
|
||||
}
|
||||
|
||||
|
||||
const std::string unit_advancements_aspect::get_value() const
|
||||
{
|
||||
return val_;
|
||||
}
|
||||
}
|
46
src/ai/lua/unit_advancements_aspect.hpp
Normal file
46
src/ai/lua/unit_advancements_aspect.hpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright (C) 2013 by Felix Bauer <fehlxb+wesnoth@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 UNIT_ADVANCEMENT_ACPECT_H_INCLUDED
|
||||
#define UNIT_ADVANCEMENT_ACPECT_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "lua/lualib.h"
|
||||
#include "../../unit_map.hpp"
|
||||
#include "../../config.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
class unit_advancements_aspect
|
||||
{
|
||||
public:
|
||||
unit_advancements_aspect();
|
||||
unit_advancements_aspect(lua_State* L, int n);
|
||||
unit_advancements_aspect(const std::string& val);
|
||||
const std::vector<std::string> get_advancements(const unit_map::const_iterator& unit) const;
|
||||
virtual ~unit_advancements_aspect()
|
||||
{
|
||||
}
|
||||
const std::string get_value() const;
|
||||
|
||||
private:
|
||||
std::string val_;
|
||||
lua_State * L_;
|
||||
int ref_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -234,6 +234,7 @@ const std::string holder::get_ai_overview()
|
|||
get_ai_ref();
|
||||
}
|
||||
std::stringstream s;
|
||||
s << "advancements: " << this->ai_->get_advancements().get_value() << std::endl;
|
||||
s << "aggression: " << this->ai_->get_aggression() << std::endl;
|
||||
s << "attack_depth: " << this->ai_->get_attack_depth() << std::endl;
|
||||
s << "caution: " << this->ai_->get_caution() << std::endl;
|
||||
|
@ -259,6 +260,7 @@ const std::string holder::get_ai_overview()
|
|||
s << "support_villages: " << this->ai_->get_support_villages() << std::endl;
|
||||
s << "village_value: " << this->ai_->get_village_value() << std::endl;
|
||||
s << "villages_per_scout: " << this->ai_->get_villages_per_scout() << std::endl;
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "testing/stage_rca.hpp"
|
||||
#include "testing/stage_fallback.hpp"
|
||||
#include "akihara/recruitment.hpp"
|
||||
#include "lua/unit_advancements_aspect.hpp"
|
||||
|
||||
namespace ai {
|
||||
// =======================================================================
|
||||
|
@ -224,6 +225,10 @@ static register_goal_factory<lua_goal>
|
|||
// =======================================================================
|
||||
|
||||
//name=composite_aspect
|
||||
|
||||
static register_aspect_factory< composite_aspect< unit_advancements_aspect > >
|
||||
advancements__composite_aspect_factory("advancements*composite_aspect");
|
||||
|
||||
static register_aspect_factory< composite_aspect<double> >
|
||||
aggression__composite_aspect_factory("aggression*composite_aspect");
|
||||
|
||||
|
@ -292,6 +297,9 @@ static register_aspect_factory< composite_aspect<int> >
|
|||
|
||||
|
||||
//name=standard_aspect
|
||||
static register_aspect_factory< standard_aspect< unit_advancements_aspect > >
|
||||
advancements__standard_aspect_factory("advancements*standard_aspect");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
aggression__standard_aspect_factory("aggression*standard_aspect");
|
||||
|
||||
|
@ -358,11 +366,15 @@ static register_aspect_factory< standard_aspect<double> >
|
|||
static register_aspect_factory< standard_aspect<int> >
|
||||
villages_per_scout__standard_aspect_factory("villages_per_scout*standard_aspect");
|
||||
|
||||
|
||||
// Also keep the old syntax
|
||||
static register_aspect_factory< testing_ai_default::aspect_attacks >
|
||||
old_attacks__testing_ai_default_aspect_attacks_factory("attacks*testing_ai_default::aspect_attacks");
|
||||
|
||||
//name = default
|
||||
static register_aspect_factory< standard_aspect< unit_advancements_aspect > >
|
||||
advancements__standard_aspect_factory2("advancements*");
|
||||
|
||||
static register_aspect_factory< standard_aspect<double> >
|
||||
aggression__standard_aspect_factory2("aggression*");
|
||||
|
||||
|
@ -429,7 +441,11 @@ static register_aspect_factory< standard_aspect<double> >
|
|||
static register_aspect_factory< standard_aspect<int> >
|
||||
villages_per_scout__standard_aspect_factory2("villages_per_scout*");
|
||||
|
||||
|
||||
//name = lua
|
||||
static register_lua_aspect_factory< lua_aspect< unit_advancements_aspect > >
|
||||
advancements__lua_aspect_factory("advancements*lua_aspect");
|
||||
|
||||
static register_lua_aspect_factory< lua_aspect<double> >
|
||||
aggression__lua_aspect_factory("aggression*lua_aspect");
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ void recruitment_phase::execute()
|
|||
analyze_potential_recruit_combat();
|
||||
|
||||
std::vector<std::string> options = get_recruitment_pattern();
|
||||
|
||||
if (std::count(options.begin(), options.end(), "scout") > 0) {
|
||||
size_t neutral_villages = 0;
|
||||
|
||||
|
@ -527,6 +528,8 @@ combat_phase::~combat_phase()
|
|||
|
||||
double combat_phase::evaluate()
|
||||
{
|
||||
std::vector<std::string> options = get_recruitment_pattern();
|
||||
|
||||
choice_rating_ = -1000.0;
|
||||
int ticks = SDL_GetTicks();
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "formula_string_utils.hpp"
|
||||
#include "gui/dialogs/game_save.hpp"
|
||||
#include "gui/dialogs/transient_message.hpp"
|
||||
#include "ai/lua/unit_advancements_aspect.hpp"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
|
@ -206,7 +207,7 @@ int advance_unit_dialog(const map_location &loc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void advance_unit(const map_location &loc, bool random_choice, bool add_replay_event)
|
||||
void advance_unit(const map_location &loc, bool automatic, bool add_replay_event, const ai::unit_advancements_aspect& advancements)
|
||||
{
|
||||
unit_map::iterator u = resources::units->find(loc);
|
||||
if(!unit_helper::will_certainly_advance(u)) {
|
||||
|
@ -218,12 +219,24 @@ void advance_unit(const map_location &loc, bool random_choice, bool add_replay_e
|
|||
|
||||
int res;
|
||||
|
||||
if (random_choice) {
|
||||
if (automatic) {
|
||||
|
||||
//if the advancements are empty or don't match any option
|
||||
//choose random instead.
|
||||
res = rand() % unit_helper::number_of_possible_advances(*u);
|
||||
|
||||
const std::vector<std::string>& options = u->advances_to();
|
||||
const std::vector<std::string>& allowed = advancements.get_advancements(u);
|
||||
|
||||
for(std::vector<std::string>::const_iterator a = options.begin(); a != options.end(); ++a) {
|
||||
if (std::find(allowed.begin(), allowed.end(), *a) != allowed.end()){
|
||||
res = a - options.begin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = advance_unit_dialog(loc);
|
||||
}
|
||||
|
||||
if(add_replay_event) {
|
||||
recorder.add_advancement(loc);
|
||||
}
|
||||
|
@ -244,7 +257,7 @@ void advance_unit(const map_location &loc, bool random_choice, bool add_replay_e
|
|||
if (u->experience() < 81) {
|
||||
// For all leveling up we have to add advancement to replay here because replay
|
||||
// doesn't handle cascading advancement since it just calls animate_unit_advancement().
|
||||
advance_unit(loc, random_choice, true);
|
||||
advance_unit(loc, automatic, true, advancements);
|
||||
} else {
|
||||
ERR_CF << "Unit has too many (" << u->experience()
|
||||
<< ") XP left; cascade leveling disabled.\n";
|
||||
|
|
|
@ -25,13 +25,19 @@ class unit_type;
|
|||
#include "map_location.hpp"
|
||||
#include "construct_dialog.hpp"
|
||||
#include "network.hpp"
|
||||
#include "ai/lua/unit_advancements_aspect.hpp"
|
||||
|
||||
namespace dialogs {
|
||||
|
||||
/**
|
||||
* Function to handle an advancing unit. If there is only one choice to advance
|
||||
* to, the unit will be automatically advanced. If there is a choice, and
|
||||
* 'random_choice' is true, then a unit will be selected at random. Otherwise,
|
||||
* to, the unit will be automatically advanced.
|
||||
|
||||
* If 'automatic' is true,
|
||||
* a unit will be selected at by given 'advancements' or at random when
|
||||
* 'advancements' is empty or don't match any possible advancement options.
|
||||
*
|
||||
* If 'automatic' is false,
|
||||
* a dialog will be displayed asking the user what to advance to.
|
||||
*
|
||||
* Note that 'loc' is not a reference, because deleting an item from the units
|
||||
|
@ -42,7 +48,7 @@ namespace dialogs {
|
|||
* cause for advancement is different (eg unstore_unit) this routine
|
||||
* should _not_ be used.
|
||||
*/
|
||||
void advance_unit(const map_location &loc, bool random_choice = false, bool add_replay_event = false);
|
||||
void advance_unit(const map_location &loc, bool automatic = false, bool add_replay_event = false, const ai::unit_advancements_aspect& advancements = ai::unit_advancements_aspect());
|
||||
|
||||
/**
|
||||
* Lets the user to select a unit advancement. This should always be used
|
||||
|
|
Loading…
Add table
Reference in a new issue