more AI/campaign tweaks

This commit is contained in:
Dave White 2004-05-17 20:43:02 +00:00
parent 83b748db1a
commit e3c775bb9e
8 changed files with 104 additions and 462 deletions

View file

@ -9,7 +9,7 @@ ggggggggggcghhhmhgggffffggggg
ggggggggggcghhhhhggggfffggggg
gggggggfggcgggvhhggggfgfggggg
gggggggfggcgggghhggggfgfgCCCg
gggggvffgfcgggghhvgggggggC1Cg
gggggvffgfcgggghhvgggggggC2Cg
ggggggffffccgggggggggggrgCCCg
gvggggfffffcgggggggrrrrgggggg
ghggggfffffcgggggrrrrgggggggg
@ -31,7 +31,7 @@ ggvggggggggggggffffgggccgggfg
gggggggggggvggggfffggdccgggfg
ggggggggggggggggggggdccdggggg
gggCCCggggggggggggggdcccvgcgg
gggC2Cgggggggggggdddccscdccgg
gggC1Cgggggggggggdddccscdccgg
gggCCCgggggggggddccccsscccscg
gggggggggggggvdcdccccssccsssc
gghghgggggggdddccccsssssssssc

View file

@ -61,15 +61,16 @@ Defeat:
description=Li'sar
side=2
canrecruit=1
facing=reverse
#ifdef EASY
gold=250
gold=150
income=5
recruit=Cavalry,Spearman,Swordsman,Mage,Ogre,Bowman
recruitment_pattern=scout,mixed fighter,fighter,fighter
#endif
#ifdef NORMAL
gold=500
gold=300
income=12
recruit=Cavalry,Swordsman,Spearman,Mage,Ogre,Bowman
recruitment_pattern=scout,mixed fighter,fighter,fighter
@ -78,7 +79,7 @@ Defeat:
recruitment_pattern=scout,fighter,fighter,fighter,archer
#ifdef HARD
gold=900
gold=500
income=20
recruit=Cavalry,Swordsman,Red Mage,Ogre,Lieutenant,Pikeman,Longbowman
recruitment_pattern=scout,mixed fighter,fighter,fighter,fighter,archer
@ -88,12 +89,12 @@ Defeat:
[/side]
[event]
name=start
[recall]
description=Delfador
[/recall]
[recall]
description=Kalenz
[/recall]
[recall]
description=Delfador
[/recall]
[recall]
description=Kalenz
[/recall]
[role]
type=Elvish Champion,Elvish Marshal,Elvish Captain,Elvish Hero,Knight,Elvish Outrider,Elvish Rider,Paladin,Mage,White Mage,Red Mage
role=Advisor
@ -139,20 +140,17 @@ Defeat:
description=Jibb
type=Lieutenant
side=2
x=6
y=32
x,y=27,12
[/unit]
[unit]
type=Swordsman
side=2
x=6
y=32
x,y=27,12
[/unit]
[unit]
type=Swordsman
side=2
x=6
y=32
x,y=27,12
[/unit]
[message]
id=msg6_6
@ -166,20 +164,17 @@ Defeat:
description=Rogerus
type=Lieutenant
side=2
x=7
y=34
x,y=27,12
[/unit]
[unit]
type=Swordsman
side=2
x=7
y=34
x,y=27,12
[/unit]
[unit]
type=Swordsman
side=2
x=7
y=34
x,y=27,12
[/unit]
[message]
id=msg6_7
@ -188,387 +183,6 @@ Defeat:
[/message]
[/event]
[event]
name=moveto
[filter]
x=6
y=32
side=1
[/filter]
[unit]
description=Henry
side=2
type=Pikeman
x=6
y=33
[/unit]
[message]
id=msg6_8
description=Henry
message="Protect the princess!!!"
[/message]
[unit]
side=2
type=Swordsman
x=5
y=33
[/unit]
[/event]
[event]
name=moveto
[filter]
x=7
y=33
side=1
[/filter]
[unit]
description=Merry
side=2
type=Pikeman
x=6
y=33
[/unit]
[message]
id=msg6_9
description=Merry
message="Stop!!!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=7
y=34
side=1
[/filter]
[unit]
description=Radalphus
side=2
type=Pikeman
x=6
y=34
[/unit]
[unit]
type=Swordsman
side=2
x=6
y=33
[/unit]
[message]
id=msg6_10
description=Radalphus
message="Halt! You shall not pass!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=7
y=35
side=1
[/filter]
[unit]
description=Guidonis
side=2
type=Pikeman
x=6
y=35
[/unit]
[unit]
type=Swordsman
side=2
x=6
y=34
[/unit]
[message]
id=msg6_11
description=Guidonis
message="My duty is to kill you!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=7
y=36
side=1
[/filter]
[unit]
description=Randulf
side=2
type=Pikeman
x=6
y=35
[/unit]
[message]
id=msg6_12
description=Randulf
message="Get out!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=7
y=36
side=1
[/filter]
[unit]
description=Bogot
side=2
type=Pikeman
x=6
y=35
[/unit]
[message]
id=msg6_13
description=Li'sar
message="Protect me!"
[/message]
[message]
id=msg6_14
description=Bogot
message="Yes, Madam!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=5
y=36
side=1
[/filter]
[unit]
description=Orry
side=2
type=Pikeman
x=5
y=35
[/unit]
[message]
id=msg6_15
description=Orry
message="Don't move!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=3
y=35
side=1
[/filter]
[unit]
description=Rook
side=2
type=Pikeman
x=4
y=35
[/unit]
[message]
id=msg6_16
description=Rook
message="Stay away!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=3
y=35
side=1
[/filter]
[unit]
description=Flinis
side=2
type=Swordsman
x=5
y=35
[/unit]
[unit]
side=2
type=Swordsman
x=4
y=34
[/unit]
[message]
id=msg6_17
description=Flinis
message="Don't move!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=12
y=31
side=1
[/filter]
[unit]
side=2
type=Red Mage
x=5
y=34
[/unit]
[message]
id=msg6_18
description=Li'sar
message="They bear down on me quickly! I had better use some magical aid."
[/message]
[/event]
[event]
name=moveto
[filter]
x=14
y=36
side=1
[/filter]
[unit]
side=2
type=Mage
x=5
y=34
[/unit]
[message]
id=msg6_19
description=Li'sar
message="They took that village, too! I'll make them retreat!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=3
y=30
side=1
[/filter]
[unit]
side=2
type=Mage
x=5
y=34
[/unit]
[message]
id=msg6_20
description=Li'sar
message="If swords cannot destroy them, magic will."
[/message]
[/event]
[event]
name=moveto
[filter]
x=5
y=33
side=1
[/filter]
[unit]
side=2
type=Red Mage
x=5
y=33
[/unit]
[message]
id=msg6_21
description=Li'sar
message="Fry them!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=5
y=35
side=1
[/filter]
[unit]
side=2
type=Red Mage
x=5
y=35
[/unit]
[message]
id=msg6_22
description=Li'sar
message="You get paid to kill them, so go!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=6
y=33
side=1
[/filter]
[unit]
side=2
type=Ogre
x=6
y=33
[/unit]
[message]
id=msg6_23
description=Li'sar
message="Somebody kill these intruders now!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=6
y=34
side=1
[/filter]
[unit]
description=Uggh
side=2
type=Ogre
x=6-9
y=34-37
[/unit]
[message]
id=msg6_24
description=Uggh
message="Uggh will kill the slime!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=4
y=33
side=1
[/filter]
[unit]
side=2
type=Ogre
x=4
y=33
[/unit]
[message]
id=msg6_25
description=Li'sar
message="Ogres! I need more ogres to defeat them!"
[/message]
[/event]
[event]
name=moveto
[filter]
x=4
y=34
side=1
[/filter]
[unit]
side=2
type=Ogre
x=3-4
y=33-34
[/unit]
[message]
id=msg6_26
description=Li'sar
message="Surely an ogre will crush them!"
[/message]
[/event]
[event]
name=die
[filter]
description=Li'sar

View file

@ -277,19 +277,12 @@ gamemap::location ai_interface::move_unit(location from, location to, std::map<l
return to;
}
gamemap::location ai::move_unit(location from, location to, std::map<location,paths>& possible_moves)
bool ai::multistep_move_possible(location from, location to, location via, std::map<location,paths>& possible_moves)
{
std::cerr << "ai::move_unit " << (from.x+1) << (from.y+1) << " -> " << (to.x+1) << "," << (to.y+1) << "\n";
std::map<location,paths> temp_possible_moves;
std::map<location,paths>* possible_moves_ptr = &possible_moves;
const unit_map::const_iterator i = units_.find(from);
if(i != units_.end() && i->second.can_recruit()) {
//if the leader isn't on its keep, and we can move to the keep and still make our planned
//movement, then try doing that.
const gamemap::location& start_pos = map_.starting_position(i->second.side());
if(i->first != start_pos && to != start_pos && units_.count(start_pos) == 0) {
std::cerr << "when seeing if leader can move from " << (from.x+1) << "," << (from.y+1) << " -> " << (to.x+1) << "," << (to.y+1) << " seeing if can detour to keep at " << (start_pos.x+1) << "," << (start_pos.y+1) << "\n";
if(i != units_.end()) {
if(from != via && to != via && units_.count(via) == 0) {
std::cerr << "when seeing if leader can move from " << (from.x+1) << "," << (from.y+1) << " -> " << (to.x+1) << "," << (to.y+1) << " seeing if can detour to keep at " << (via.x+1) << "," << (via.y+1) << "\n";
const std::map<location,paths>::const_iterator moves = possible_moves.find(from);
if(moves != possible_moves.end()) {
@ -298,46 +291,63 @@ gamemap::location ai::move_unit(location from, location to, std::map<location,pa
bool can_make_it = false;
int move_left = 0;
//see if the leader can make it to the keep, and if it can, how much movement it
//will have left when it gets there.
const paths::routes_map::const_iterator itor = moves->second.routes.find(start_pos);
//see if the unit can make it to 'via', and if it can, how much movement it will have
//left when it gets there.
const paths::routes_map::const_iterator itor = moves->second.routes.find(via);
if(itor != moves->second.routes.end()) {
move_left = itor->second.move_left;
std::cerr << "can make it to keep with " << move_left << " movement left\n";
unit temp_unit(i->second);
temp_unit.set_movement(move_left);
const temporary_unit_placer unit_placer(units_,start_pos,temp_unit);
const paths leader_paths(map_,state_,gameinfo_,units_,start_pos,teams_,false,false);
const temporary_unit_placer unit_placer(units_,via,temp_unit);
const paths unit_paths(map_,state_,gameinfo_,units_,via,teams_,false,false);
std::cerr << "found " << leader_paths.routes.size() << " moves for temp leader\n";
std::cerr << "found " << unit_paths.routes.size() << " moves for temp leader\n";
//see if this leader could make it back to the keep
if(leader_paths.routes.count(to) != 0) {
if(unit_paths.routes.count(to) != 0) {
std::cerr << "can make it back to the keep\n";
can_make_it = true;
return true;
}
}
//if we can make it back to the keep and then to our original destination, do so.
if(can_make_it) {
from = ai_interface::move_unit(from,start_pos,possible_moves);
if(from != start_pos) {
return from;
}
const unit_map::iterator itor = units_.find(from);
if(itor != units_.end()) {
std::cerr << "setting temp moves of unit to " << move_left << "\n";
itor->second.set_movement(move_left);
}
move_map srcdst, dstsrc;
calculate_possible_moves(temp_possible_moves,srcdst,dstsrc,false);
possible_moves_ptr = &temp_possible_moves;
}
}
}
}
return false;
}
gamemap::location ai::move_unit(location from, location to, std::map<location,paths>& possible_moves)
{
std::cerr << "ai::move_unit " << (from.x+1) << (from.y+1) << " -> " << (to.x+1) << "," << (to.y+1) << "\n";
std::map<location,paths> temp_possible_moves;
std::map<location,paths>* possible_moves_ptr = &possible_moves;
const unit_map::const_iterator i = units_.find(from);
if(i != units_.end() && i->second.can_recruit()) {
//if the leader isn't on its keep, and we can move to the keep and still make our planned
//movement, then try doing that.
const gamemap::location& start_pos = map_.starting_position(i->second.side());
//if we can make it back to the keep and then to our original destination, do so.
if(multistep_move_possible(from,to,start_pos,possible_moves)) {
from = ai_interface::move_unit(from,start_pos,possible_moves);
if(from != start_pos) {
return from;
}
const unit_map::iterator itor = units_.find(from);
if(itor != units_.end()) {
//just set the movement to one less than the maximum possible, since we know we
//can reach the destination, and we're giong to move there immediately
itor->second.set_movement(itor->second.total_movement()-1);
}
move_map srcdst, dstsrc;
calculate_possible_moves(temp_possible_moves,srcdst,dstsrc,false);
possible_moves_ptr = &temp_possible_moves;
}
do_recruitment();
}
@ -695,6 +705,9 @@ std::vector<std::pair<gamemap::location,gamemap::location> > ai::get_village_com
bool ai::get_villages(std::map<gamemap::location,paths>& possible_moves, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_srcdst, const move_map& enemy_dstsrc, unit_map::const_iterator leader)
{
std::cerr << "deciding which villages we want...\n";
const location& start_pos = map_.starting_position(team_num_);
//we want to build up a list of possible moves we can make that will capture villages.
//limit the moves to 'max_village_moves' to make sure things don't get out of hand.
const size_t max_village_moves = 50;
@ -716,16 +729,24 @@ bool ai::get_villages(std::map<gamemap::location,paths>& possible_moves, const m
}
}
if(want_village == false) {
continue;
}
//if it's a neutral village, and we have no leader, then the village is no use to us,
//and we don't want it.
if(!owned && leader == units_.end()) {
want_village = false;
continue;
}
if(want_village) {
std::cerr << "want village at " << (j->first.x+1) << "," << (j->first.y+1) << "\n";
village_moves.push_back(*j);
//if we have a decent amount of gold, and the leader can't access the keep this turn if they get this village
//then don't get this village with them
if(want_village && leader != units_.end() && current_team().gold() > 20 && leader->first == j->second &&
leader->first != start_pos && multistep_move_possible(j->second,j->first,start_pos,possible_moves) == false) {
continue;
}
village_moves.push_back(*j);
}
std::set<location> taken_villages, moved_units;
@ -763,7 +784,7 @@ bool ai::get_healing(std::map<gamemap::location,paths>& possible_moves, const mo
Itor best_loc = it.second;
while(it.first != it.second) {
const location& dst = it.first->second;
if(map_.gives_healing(dst) && units_.find(dst) == units_.end()) {
if(map_.gives_healing(dst) && (units_.find(dst) == units_.end() || dst == u_it->first)) {
const double vuln = power_projection(it.first->first,
enemy_srcdst,enemy_dstsrc);
std::cerr << "found village with vulnerability: " << vuln << "\n";

View file

@ -350,6 +350,9 @@ protected:
//moving, it will first attempt recruitment.
location move_unit(location from, location to, std::map<location,paths>& possible_moves);
//sees if it's possible for a unit to move 'from' -> 'via' -> 'to' all in one turn
bool multistep_move_possible(location from, location to, location via, std::map<location,paths>& possible_moves);
struct attack_analysis
{
void analyze(const gamemap& map, std::map<location,unit>& units,

View file

@ -182,10 +182,10 @@ class invalid_utf8_exception : public std::exception {
namespace
{
std::string wstring_to_utf8(const std::wstring &src)
std::string wstring_to_utf8(const wide_string &src)
{
wchar_t ch;
std::wstring::const_iterator i;
wide_string::const_iterator i;
int j;
Uint32 bitmask;
std::string ret;
@ -232,9 +232,9 @@ std::string wstring_to_utf8(const std::wstring &src)
}
}
std::wstring utf8_to_wstring(const std::string &src)
wide_string utf8_to_wstring(const std::string &src)
{
std::wstring ret;
wide_string ret;
wchar_t ch;
std::string::const_iterator i;
@ -288,14 +288,14 @@ std::wstring utf8_to_wstring(const std::string &src)
}
std::string wstring_to_string(const std::wstring &src)
std::string wstring_to_string(const wide_string &src)
{
if(charset() == CHARSET_UTF8) {
return wstring_to_utf8(src);
}
std::string ret;
for(std::wstring::const_iterator itor = src.begin(); itor != src.end(); ++itor) {
for(wide_string::const_iterator itor = src.begin(); itor != src.end(); ++itor) {
if(*itor <= 0xff) {
push_back(ret,*itor);
} else {
@ -305,13 +305,13 @@ std::string wstring_to_string(const std::wstring &src)
return ret;
}
std::wstring string_to_wstring(const std::string &src)
wide_string string_to_wstring(const std::string &src)
{
if(charset() == CHARSET_UTF8) {
return utf8_to_wstring(src);
}
std::wstring ret;
wide_string ret;
ret.resize(src.size());
std::copy(src.begin(),src.end(),ret.begin());

View file

@ -19,6 +19,9 @@
#include <string>
#include <vector>
//the type we use to represent Unicode strings.
typedef std::vector<wchar_t> wide_string;
//this module controls internationalization.
struct symbol_table
@ -58,8 +61,8 @@ std::string get_locale();
//functions for converting Unicode wide-char strings to UTF-8 encoded
//strings, back and forth
std::string wstring_to_string(const std::wstring &);
std::wstring string_to_wstring(const std::string &);
std::string wstring_to_string(const wide_string &);
wide_string string_to_wstring(const std::string &);
//two character sets are supported: LATIN1 and UTF-8. This is

View file

@ -57,7 +57,7 @@ void textbox::set_text(std::string text)
void textbox::clear()
{
text_ = L"";
text_.clear();
cursor_ = 0;
cursor_pos_ = 0;
text_pos_ = 0;
@ -249,10 +249,10 @@ void textbox::update_text_cache(bool changed)
// actually be done by the font-rendering system.
std::string visible_string;
std::wstring wrapped_text;
wide_string wrapped_text;
for(std::wstring::const_iterator itor = text_.begin(); itor != text_.end(); itor++) {
std::wstring s;
for(wide_string::const_iterator itor = text_.begin(); itor != text_.end(); itor++) {
wide_string s;
push_back(s,*itor);
visible_string.append(wstring_to_string(s));
@ -303,7 +303,7 @@ void textbox::erase_selection()
if(!is_selection())
return;
std::wstring::iterator itor = text_.begin() + minimum(selstart_, selend_);
wide_string::iterator itor = text_.begin() + minimum(selstart_, selend_);
text_.erase(itor, itor + abs(selend_ - selstart_));
cursor_ = minimum(selstart_, selend_);
selstart_ = selend_ = -1;

View file

@ -16,6 +16,7 @@
#include "../events.hpp"
#include "../key.hpp"
#include "../language.hpp"
#include "../sdl_utils.hpp"
#include "button.hpp"
@ -48,7 +49,7 @@ public:
private:
void scroll(int pos);
std::wstring text_;
wide_string text_;
// mutable unsigned int firstOnScreen_;
int cursor_;