Skip to content

Commit

Permalink
Generalizing the FAI concept of action objects
Browse files Browse the repository at this point in the history
  • Loading branch information
CelticMinstrel committed Apr 2, 2017
1 parent d2caa16 commit 7c5411c
Show file tree
Hide file tree
Showing 11 changed files with 433 additions and 416 deletions.
59 changes: 59 additions & 0 deletions src/ai/default/attack.cpp
Expand Up @@ -19,6 +19,9 @@

#include "ai/manager.hpp"
#include "ai/default/contexts.hpp"
#include "ai/actions.hpp"
#include "ai/formula/ai.hpp"
#include "ai/composite/contexts.hpp"

#include "actions/attack.hpp"
#include "attack_prediction.hpp"
Expand All @@ -28,13 +31,17 @@
#include "team.hpp"
#include "units/unit.hpp"
#include "formula/callable_objects.hpp" // for location_callable
#include "resources.hpp"
#include "game_board.hpp"

static lg::log_domain log_ai("ai/attack");
#define LOG_AI LOG_STREAM(info, log_ai)
#define ERR_AI LOG_STREAM(err, log_ai)

namespace ai {

extern ai_context& get_ai_context(const game_logic::formula_callable* for_fai);

void attack_analysis::analyze(const gamemap& map, unit_map& units,
const readonly_context& ai_obj,
const move_map& dstsrc, const move_map& srcdst,
Expand Down Expand Up @@ -400,4 +407,56 @@ void attack_analysis::get_inputs(game_logic::formula_input_vector* inputs) const
add_input(inputs, "is_surrounded");
}

variant attack_analysis::execute_self(variant ctxt) {
//If we get an attack analysis back we will do the first attack.
//Then the AI can get run again and re-choose.
if(movements.empty()) {
return variant(false);
}

unit_map& units = resources::gameboard->units();

//make sure that unit which has to attack is at given position and is able to attack
unit_map::const_iterator unit = units.find(movements.front().first);
if(!unit.valid() || unit->attacks_left() == 0) {
return variant(false);
}

const map_location& move_from = movements.front().first;
const map_location& att_src = movements.front().second;
const map_location& att_dst = target;

//check if target is still valid
unit = units.find(att_dst);
if(unit == units.end()) {
return variant(new game_logic::safe_call_result(this, attack_result::E_EMPTY_DEFENDER, move_from));
}

//check if we need to move
if(move_from != att_src) {
//now check if location to which we want to move is still unoccupied
unit = units.find(att_src);
if(unit != units.end()) {
return variant(new game_logic::safe_call_result(this, move_result::E_NO_UNIT, move_from));
}

ai::move_result_ptr result = get_ai_context(ctxt.as_callable()).execute_move_action(move_from, att_src);
if(!result->is_ok()) {
//move part failed
LOG_AI << "ERROR #" << result->get_status() << " while executing 'attack' formula function\n" << std::endl;
return variant(new game_logic::safe_call_result(this, result->get_status(), result->get_unit_location()));
}
}

if(units.count(att_src)) {
ai::attack_result_ptr result = get_ai_context(ctxt.as_callable()).execute_attack_action(movements.front().second, target, -1);
if(!result->is_ok()) {
//attack failed
LOG_AI << "ERROR #" << result->get_status() << " while executing 'attack' formula function\n" << std::endl;
return variant(new game_logic::safe_call_result(this, result->get_status()));
}
}
return variant(true);
}

} //end of namespace ai
5 changes: 3 additions & 2 deletions src/ai/default/contexts.hpp
Expand Up @@ -55,11 +55,11 @@ struct target {
};


class attack_analysis : public game_logic::formula_callable
class attack_analysis : public game_logic::action_callable
{
public:
attack_analysis() :
game_logic::formula_callable(),
game_logic::action_callable(),
target(),
movements(),
target_value(0.0),
Expand Down Expand Up @@ -138,6 +138,7 @@ class attack_analysis : public game_logic::formula_callable
/** Is true if the units involved in this attack sequence are surrounded. */
bool is_surrounded;

variant execute_self(variant ctxt) override;
};


Expand Down

0 comments on commit 7c5411c

Please sign in to comment.