some AI improvements
This commit is contained in:
parent
bf18668a1e
commit
688ad5a231
7 changed files with 88 additions and 17 deletions
82
src/ai.cpp
82
src/ai.cpp
|
@ -203,8 +203,9 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
for(paths::routes_map::const_iterator rt = new_paths.routes.begin();
|
||||
rt != new_paths.routes.end(); ++rt) {
|
||||
const std::pair<location,location> item(un_it->first,rt->first);
|
||||
const std::pair<location,location> item_reverse(rt->first,un_it->first);
|
||||
enemy_srcdst.insert(item);
|
||||
enemy_dstsrc.insert(item);
|
||||
enemy_dstsrc.insert(item_reverse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,9 +251,32 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
|
||||
const unit_map::iterator leader = find_leader(units,team_num);
|
||||
|
||||
//no moves left, recruitment phase
|
||||
//no moves left, recruitment phase and leader movement phase
|
||||
//take stock of our current set of units
|
||||
if(srcdst.empty()) {
|
||||
if(srcdst.empty() || leader != units.end() && srcdst.count(leader->first) == srcdst.size()) {
|
||||
if(leader == units.end()) {
|
||||
recorder.end_turn();
|
||||
return;
|
||||
}
|
||||
|
||||
//find where the leader can move
|
||||
const paths leader_paths(map,gameinfo,units,leader->first,teams,false,false);
|
||||
const gamemap::location& start_pos = map.starting_position(leader->second.side());
|
||||
|
||||
possible_moves.insert(std::pair<gamemap::location,paths>(leader->first,leader_paths));
|
||||
|
||||
bool leader_moved = false;
|
||||
//if the leader is not on his starting location, move him there.
|
||||
if(leader->first != start_pos) {
|
||||
leader_moved = true;
|
||||
const paths::routes_map::const_iterator itor = leader_paths.routes.find(start_pos);
|
||||
if(itor != leader_paths.routes.end()) {
|
||||
move_unit(gameinfo,disp,map,units,leader->first,start_pos,
|
||||
possible_moves,teams,team_num);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "recruitment......\n";
|
||||
|
||||
//currently just spend all the gold we can!
|
||||
|
@ -293,6 +317,52 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
|
||||
}
|
||||
|
||||
//see if the leader can capture a village safely
|
||||
if(!leader_moved) {
|
||||
//if the keep is accessible by an enemy unit, we don't want to leave it
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(leader->first,adj);
|
||||
for(size_t n = 0; n != 6; ++n) {
|
||||
if(enemy_dstsrc.count(adj[n])) {
|
||||
leader_moved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//search through villages finding one to capture
|
||||
if(!leader_moved) {
|
||||
const std::vector<gamemap::location>& villages = map.towers();
|
||||
for(std::vector<gamemap::location>::const_iterator v = villages.begin();
|
||||
v != villages.end(); ++v) {
|
||||
const paths::routes_map::const_iterator itor = leader_paths.routes.find(*v);
|
||||
if(itor == leader_paths.routes.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int owner = tower_owner(*v,teams);
|
||||
if(owner == -1 || current_team.is_enemy(owner+1) || leader->second.hitpoints() < leader->second.max_hitpoints()) {
|
||||
|
||||
//check that no enemies can reach the village
|
||||
gamemap::location adj[6];
|
||||
get_adjacent_tiles(*v,adj);
|
||||
size_t n;
|
||||
for(n = 0; n != 6; ++n) {
|
||||
if(enemy_dstsrc.count(adj[n]))
|
||||
break;
|
||||
}
|
||||
|
||||
if(n != 6)
|
||||
continue;
|
||||
|
||||
move_unit(gameinfo,disp,map,units,leader->first,*v,
|
||||
possible_moves,teams,team_num);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recorder.end_turn();
|
||||
return;
|
||||
}
|
||||
|
@ -401,12 +471,6 @@ void do_move(display& disp, const gamemap& map, const game_data& gameinfo,
|
|||
//mark the leader as having moved and attacked by now
|
||||
for(std::vector<location>::const_iterator lead = leader_locations.begin();
|
||||
lead != leader_locations.end(); ++lead) {
|
||||
const std::map<location,unit>::iterator leader = units.find(*lead);
|
||||
if(leader != units.end()) {
|
||||
leader->second.set_movement(0);
|
||||
leader->second.set_attacked();
|
||||
}
|
||||
|
||||
//remove leader from further consideration
|
||||
srcdst.erase(*lead);
|
||||
dstsrc.erase(*lead);
|
||||
|
|
|
@ -70,7 +70,7 @@ struct move_cost_calculator
|
|||
*/
|
||||
double res = modifier*move_cost + enemies*2.0;
|
||||
|
||||
//if there is a unit (even a friendly one) on this tile, we increase the cost
|
||||
//if there is a unit (even a friendly one) on this tile, we increase the cost to
|
||||
//try discourage going through units, to thwart the 'single file effect'
|
||||
if(units_.count(loc))
|
||||
res *= 4.0;
|
||||
|
|
|
@ -296,8 +296,6 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
|
|||
bool is_format_char(char c)
|
||||
{
|
||||
switch(c) {
|
||||
case '+':
|
||||
case '-':
|
||||
case '#':
|
||||
case '@':
|
||||
return true;
|
||||
|
|
|
@ -681,7 +681,7 @@ void event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
|
||||
//if we're not replaying, or if there is no choice to be made, show
|
||||
//the dialog.
|
||||
if(recorder.at_end() == false || options.empty()) {
|
||||
if(recorder.at_end() || options.empty()) {
|
||||
option_chosen = gui::show_dialog(*screen,surface,caption,
|
||||
lang_message.empty() ? cfg["message"] : lang_message,
|
||||
options.empty() ? gui::MESSAGE : gui::OK_ONLY,
|
||||
|
@ -693,7 +693,7 @@ void event_handler::handle_event_command(const queued_event& event_info, const s
|
|||
}
|
||||
|
||||
//otherwise if a choice has to be made, get it from the replay data
|
||||
else if(options.empty() == false) {
|
||||
else {
|
||||
const config* const action = recorder.get_next_action();
|
||||
if(action == NULL || action->get_children("choose").empty()) {
|
||||
std::cerr << "choice expected but none found\n";
|
||||
|
|
|
@ -79,6 +79,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
|
||||
const bool modify_placing = (*level)["modify_placing"] == "true";
|
||||
std::set<int> taken_places;
|
||||
std::vector<gamemap::location> starting_locs;
|
||||
|
||||
const config::child_list& unit_cfg = level->get_children("side");
|
||||
for(config::child_list::const_iterator ui = unit_cfg.begin(); ui != unit_cfg.end(); ++ui) {
|
||||
|
@ -135,6 +136,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
assert(start != -1);
|
||||
|
||||
const gamemap::location& start_pos = map.starting_position(start);
|
||||
starting_locs.push_back(start_pos);
|
||||
|
||||
if(!start_pos.valid() && new_unit.side() == 1) {
|
||||
throw gamestatus::load_game_failed("No starting position for side 1");
|
||||
|
@ -177,6 +179,10 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
}
|
||||
}
|
||||
|
||||
for(size_t pos = 0; pos != starting_locs.size(); ++pos) {
|
||||
map.set_starting_position(pos+1,starting_locs[pos]);
|
||||
}
|
||||
|
||||
const teams_manager team_manager(teams);
|
||||
|
||||
const config* const theme_cfg = game_config.find_child("theme","name",preferences::theme());
|
||||
|
@ -235,6 +241,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& game_config,
|
|||
const hotkey::basic_handler key_events_handler(gui);
|
||||
clear_shroud(gui,map,gameinfo,units,teams,0);
|
||||
|
||||
std::cerr << "first_time..." << (recorder.skipping() ? "skipping" : "no skip") << "\n";
|
||||
update_locker lock_display(gui,recorder.skipping());
|
||||
game_events::fire("start");
|
||||
gui.draw();
|
||||
|
@ -474,6 +481,7 @@ redo_turn:
|
|||
event_stream << "turn " << status.turn();
|
||||
|
||||
{
|
||||
std::cerr << "turn event..." << (recorder.skipping() ? "skipping" : "no skip") << "\n";
|
||||
update_locker lock_display(gui,recorder.skipping());
|
||||
game_events::fire(event_stream.str());
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ void replay::next_skip()
|
|||
|
||||
bool replay::skipping() const
|
||||
{
|
||||
return skip_ != 0;
|
||||
return at_end() == false && skip_ != 0;
|
||||
}
|
||||
|
||||
void replay::save_game(game_data& data, const std::string& label, const config& start_pos,
|
||||
|
@ -273,6 +273,7 @@ void replay::mark_current()
|
|||
|
||||
config* replay::add_command()
|
||||
{
|
||||
pos_ = ncommands()+1;
|
||||
return current_ = &cfg_.add_child("command");
|
||||
}
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
str << status.turn() << "/" << status.number_of_turns() << "\n";
|
||||
break;
|
||||
case GOLD:
|
||||
str << current_team.gold();
|
||||
str << (current_team.gold() < 0 ? "#" : "") << current_team.gold();
|
||||
break;
|
||||
case VILLAGES: {
|
||||
const team_data data = calculate_team_data(current_team,current_side,units);
|
||||
|
@ -199,7 +199,7 @@ report generate_report(TYPE type, const gamemap& map, const unit_map& units,
|
|||
}
|
||||
case INCOME: {
|
||||
const team_data data = calculate_team_data(current_team,current_side,units);
|
||||
str << data.net_income;
|
||||
str << (data.net_income < 0 ? "#" : "") << data.net_income;
|
||||
break;
|
||||
}
|
||||
case TERRAIN: {
|
||||
|
|
Loading…
Add table
Reference in a new issue