wesnoth-cvs-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Wesnoth-cvs-commits] wesnoth ./configure src/game.cpp src/game_event...


From: David White
Subject: [Wesnoth-cvs-commits] wesnoth ./configure src/game.cpp src/game_event...
Date: Sun, 12 Sep 2004 23:21:38 -0400

CVSROOT:        /cvsroot/wesnoth
Module name:    wesnoth
Branch:         
Changes by:     David White <address@hidden>    04/09/13 03:16:19

Modified files:
        .              : configure 
        src            : game.cpp game_events.cpp gamestatus.cpp 
                         gamestatus.hpp multiplayer.cpp 
                         multiplayer_client.cpp multiplayer_connect.cpp 
                         playlevel.cpp playturn.cpp publish_campaign.cpp 
                         replay.cpp team.cpp team.hpp 

Log message:
        patch to allow multiple recall lists

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/configure.diff?tr1=1.107&tr2=1.108&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/game.cpp.diff?tr1=1.128&tr2=1.129&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/game_events.cpp.diff?tr1=1.102&tr2=1.103&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/gamestatus.cpp.diff?tr1=1.41&tr2=1.42&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/gamestatus.hpp.diff?tr1=1.30&tr2=1.31&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer.cpp.diff?tr1=1.118&tr2=1.119&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer_client.cpp.diff?tr1=1.62&tr2=1.63&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer_connect.cpp.diff?tr1=1.64&tr2=1.65&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/playlevel.cpp.diff?tr1=1.152&tr2=1.153&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/playturn.cpp.diff?tr1=1.263&tr2=1.264&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/publish_campaign.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/replay.cpp.diff?tr1=1.79&tr2=1.80&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/team.cpp.diff?tr1=1.70&tr2=1.71&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/team.hpp.diff?tr1=1.49&tr2=1.50&r1=text&r2=text

Patches:
Index: wesnoth/configure
diff -u wesnoth/configure:1.107 wesnoth/configure:1.108
--- wesnoth/configure:1.107     Sun Sep 12 21:55:18 2004
+++ wesnoth/configure   Mon Sep 13 03:16:19 2004
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 1.85 .
+# From configure.ac Revision: 1.86 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59 for Battle for Wesnoth 0.8.5-CVS.
 #
Index: wesnoth/src/game.cpp
diff -u wesnoth/src/game.cpp:1.128 wesnoth/src/game.cpp:1.129
--- wesnoth/src/game.cpp:1.128  Sun Sep 12 23:13:35 2004
+++ wesnoth/src/game.cpp        Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: game.cpp,v 1.128 2004/09/12 23:13:35 Sirp Exp $ */
+/* $Id: game.cpp,v 1.129 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -927,7 +927,7 @@
                                config starting_pos;
                                if(recorder.at_end()) {
                                        starting_pos = state.snapshot;
-                                       state.gold = -100000;
+                                        // state.gold = -100000;
                                } else {
                                        starting_pos = state.starting_pos;
                                }
Index: wesnoth/src/game_events.cpp
diff -u wesnoth/src/game_events.cpp:1.102 wesnoth/src/game_events.cpp:1.103
--- wesnoth/src/game_events.cpp:1.102   Sun Sep 12 03:00:04 2004
+++ wesnoth/src/game_events.cpp Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: game_events.cpp,v 1.102 2004/09/12 03:00:04 Sirp Exp $ */
+/* $Id: game_events.cpp,v 1.103 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -38,8 +38,7 @@
        //an 'or' statement means that if the contained statements are true,
        //then it automatically passes
        const config::child_list& or_statements = cond.get_children("or");
-       for(config::child_list::const_iterator or_it = or_statements.begin();
-           or_it != or_statements.end(); ++or_it) {
+       for(config::child_list::const_iterator or_it = or_statements.begin(); 
or_it != or_statements.end(); ++or_it) {
                if(conditional_passed(units,**or_it)) {
                        return true;
                }
@@ -49,8 +48,7 @@
        //check for that.
        const config::child_list& have_unit = cond.get_children("have_unit");
 
-       for(config::child_list::const_iterator u = have_unit.begin();
-           u != have_unit.end(); ++u) {
+       for(config::child_list::const_iterator u = have_unit.begin(); u != 
have_unit.end(); ++u) {
 
                if(units == NULL)
                        return false;
@@ -70,8 +68,7 @@
        //check against each variable statement to see if the variable
        //matches the conditions or not
        const config::child_list& variables = cond.get_children("variable");
-       for(config::child_list::const_iterator var = variables.begin();
-           var != variables.end(); ++var) {
+       for(config::child_list::const_iterator var = variables.begin(); var != 
variables.end(); ++var) {
                const config& values = **var;
 
                const std::string& name = values["name"];
@@ -296,8 +293,10 @@
                for(std::vector<std::string>::const_iterator i = types.begin(); 
i != types.end(); ++i) {
                        (*teams)[index].recruits().insert(*i);
                        preferences::encountered_units().insert(*i);
-                       if(index == 0) {
-                               state_of_game->can_recruit.insert(*i);
+
+                        player_info 
*player=state_of_game->get_player((*teams)[index].save_id());
+                        if(player) {
+                                player->can_recruit.insert(*i);
                        }
                }
        }
@@ -313,8 +312,10 @@
                const std::vector<std::string>& types = config::split(type);
                for(std::vector<std::string>::const_iterator i = types.begin(); 
i != types.end(); ++i) {
                        (*teams)[index].recruits().erase(*i);
-                       if(index == 0) {
-                               state_of_game->can_recruit.erase(*i);
+
+                        player_info 
*player=state_of_game->get_player((*teams)[index].save_id());
+                        if(player) {
+                                player->can_recruit.erase(*i);
                        }
                }
        }
@@ -332,8 +333,10 @@
                std::set<std::string>& can_recruit = (*teams)[index].recruits();
                can_recruit.clear();
                
std::copy(recruit.begin(),recruit.end(),std::inserter(can_recruit,can_recruit.end()));
-               if(index == 0) {
-                       state_of_game->can_recruit = can_recruit;
+
+                player_info 
*player=state_of_game->get_player((*teams)[index].save_id());
+                if(player) {
+                        player->can_recruit = can_recruit;
                }
        }
 
@@ -612,12 +615,15 @@
                //get a list of the types this unit can be
                std::vector<std::string> types = config::split(cfg["type"]);
 
+                std::vector<std::string> sides = config::split(cfg["side"]);
+
                //iterate over all the types, and for each type, try to find
                //a unit that matches
                std::vector<std::string>::iterator ti;
                for(ti = types.begin(); ti != types.end(); ++ti) {
                        config item = cfg;
                        item["type"] = *ti;
+                        item["side"] = cfg["side"];
                        item["role"] = "";
 
                        std::map<gamemap::location,unit>::iterator itor;
@@ -631,19 +637,49 @@
                        if(itor != units->end())
                                break;
 
-                       std::vector<unit>::iterator ui;
-                       //iterate over the units, and try to find one that 
matches
-                       for(ui = state_of_game->available_units.begin();
-                           ui != state_of_game->available_units.end(); ++ui) {
-                               if(game_events::unit_matches_filter(*ui,item)) {
-                                       ui->assign_role(cfg["role"]);
-                                       break;
-                               }
+                        bool found = false;
+
+                        if(sides.empty() == false) {
+                          std::vector<std::string>::const_iterator si;
+                          for(si = sides.begin(); si != sides.end(); ++si) {
+                            int side_num = lexical_cast_default<int>(*si,1);
+
+                            player_info* 
player=state_of_game->get_player((*teams)[side_num-1].save_id());
+
+                            if(!player)
+                              continue;
+
+                            //iterate over the units, and try to find one that 
matches
+                            std::vector<unit>::iterator ui;
+                            for(ui = player->available_units.begin();
+                                ui != player->available_units.end(); ++ui) {
+                              if(game_events::unit_matches_filter(*ui, item)) {
+                                ui->assign_role(cfg["role"]);
+                                found=true;
+                                break;
+                              }
+                            }
+                          }
+                        } else {
+                          std::map<std::string, player_info>::iterator pi;
+                          for(pi=state_of_game->players.begin();
+                              pi!=state_of_game->players.end(); ++pi) {
+                            std::vector<unit>::iterator ui;
+                            //iterate over the units, and try to find one that 
matches
+                            for(ui = pi->second.available_units.begin();
+                                ui != pi->second.available_units.end(); ++ui) {
+                              if(game_events::unit_matches_filter(*ui, item)) {
+                                ui->assign_role(cfg["role"]);
+                                found=true;
+                                break;
+                              }
+                            }
+                          }
                        }
 
                        //if we found a unit, we don't have to keep going.
-                       if(ui != state_of_game->available_units.end())
-                               break;
+                        if(found)
+                          break;
                }
        }
 
@@ -728,21 +764,32 @@
 
                        screen->invalidate(loc);
                } else {
-                       state_of_game->available_units.push_back(new_unit);
+                  player_info 
*player=state_of_game->get_player((*teams)[new_unit.side()-1].save_id());
+
+                  if(player) {
+                    player->available_units.push_back(new_unit);
+                  } else {
+                    std::cerr << "Cannot create unit: location is not on the 
map, and player " << new_unit.side() << " has no recall list." << std::endl;
+                  }
                }
        }
 
        //if we should recall units that match a certain description
        else if(cmd == "recall") {
-               std::vector<unit>& avail = state_of_game->available_units;
-               for(std::vector<unit>::iterator u = avail.begin(); u != 
avail.end(); ++u) {
-                       if(game_events::unit_matches_filter(*u,cfg)) {
-                               gamemap::location loc(cfg);
-                               
recruit_unit(*game_map,1,*units,*u,loc,cfg["show"] == "no" ? NULL : 
screen,false,true);
-                               avail.erase(u);
-                               break;
-                       }
-               }
+          for(int index=0; index<teams->size(); ++index) {
+            player_info 
*player=state_of_game->get_player((*teams)[index].save_id());
+
+            std::vector<unit>& avail = player->available_units;
+
+            for(std::vector<unit>::iterator u = avail.begin(); u != 
avail.end(); ++u) {
+              if(game_events::unit_matches_filter(*u,cfg)) {
+                gamemap::location loc(cfg);
+                recruit_unit(*game_map,index+1,*units,*u,loc,cfg["show"] == 
"no" ? NULL : screen,false,true);
+                avail.erase(u);
+                break;
+              }
+            }
+          }
        }
 
        else if(cmd == "object") {
@@ -974,7 +1021,6 @@
        }
 
        else if(cmd == "kill") {
-
                for(unit_map::iterator un = units->begin(); un != 
units->end();) {
                        if(game_events::unit_matches_filter(un,cfg)) {
                                if(cfg["animate"] == "yes") {
@@ -993,16 +1039,21 @@
                }
 
                //if the filter doesn't contain positional information, then it 
may match
-               //units on the recall list.
+                //units on all recall lists.
                if(cfg["x"].empty() && cfg["y"].empty()) {
-                       std::vector<unit>& avail_units = 
state_of_game->available_units;
+                  std::map<std::string, player_info>& 
players=state_of_game->players;
+
+                  for(std::map<std::string, player_info>::iterator pi = 
players.begin();
+                      pi!=players.end(); ++pi) {
+                        std::vector<unit>& avail_units = 
pi->second.available_units;
                        for(std::vector<unit>::iterator j = 
avail_units.begin(); j != avail_units.end();) {
-                               if(game_events::unit_matches_filter(*j,cfg)) {
-                                       j = avail_units.erase(j);
-                               } else {
-                                       ++j;
-                               }
+                          if(game_events::unit_matches_filter(*j, cfg)) {
+                            j = avail_units.erase(j);
+                          } else {
+                            ++j;
+                          }
                        }
+                  }
                }
        }
 
@@ -1043,24 +1094,29 @@
                }
 
                if(filter["x"].empty() && filter["y"].empty()) {
-                       std::vector<unit>& avail_units = 
state_of_game->available_units;
-                       for(std::vector<unit>::iterator j = 
avail_units.begin(); j != avail_units.end();) {
-                               if(game_events::unit_matches_filter(*j,filter) 
== false) {
-                                       ++j;
-                                       continue;
-                               }
+                  std::map<std::string, player_info>& players = 
state_of_game->players;
+
+                  for(std::map<std::string, player_info>::iterator pi = 
players.begin();
+                      pi!=players.end(); ++pi) {
+                    std::vector<unit>& avail_units = 
pi->second.available_units;
+                    for(std::vector<unit>::iterator j = avail_units.begin(); j 
!= avail_units.end();) {
+                      if(game_events::unit_matches_filter(*j, filter) == 
false) {
+                        ++j;
+                        continue;
+                      }
        
-                               config& data = vars.add_child(variable);
-                               j->write(data);
-                               data["x"] = "recall";
-                               data["y"] = "recall";
+                      config& data = vars.add_child(variable);
+                      j->write(data);
+                      data["x"] = "recall";
+                      data["y"] = "recall";
        
-                               if(kill_units) {
-                                       j = avail_units.erase(j);
-                               } else {
-                                       ++j;
-                               }
-                       }
+                      if(kill_units) {
+                        j = avail_units.erase(j);
+                      } else {
+                        ++j;
+                      }
+                    }
+                  }
                }
        }
 
@@ -1078,7 +1134,13 @@
                                units->erase(loc);
                                
units->insert(std::pair<gamemap::location,unit>(loc,u));
                        } else {
-                               state_of_game->available_units.push_back(u);
+                          player_info 
*player=state_of_game->get_player((*teams)[u.side()-1].save_id());
+
+                          if(player) {
+                            player->available_units.push_back(u);
+                          } else {
+                            std::cerr << "Cannot unstore unit: no recall list 
for player " << u.side() << " and the map location is invalid." << std::endl;
+                          }
                        }
                } catch(gamestatus::load_game_failed& e) {
                        std::cerr << "could not de-serialize unit: '" << 
e.message << "'\n";
Index: wesnoth/src/gamestatus.cpp
diff -u wesnoth/src/gamestatus.cpp:1.41 wesnoth/src/gamestatus.cpp:1.42
--- wesnoth/src/gamestatus.cpp:1.41     Sun Aug 29 16:09:57 2004
+++ wesnoth/src/gamestatus.cpp  Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: gamestatus.cpp,v 1.41 2004/08/29 16:09:57 Sirp Exp $ */
+/* $Id: gamestatus.cpp,v 1.42 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -192,15 +192,53 @@
        return numTurns_ == -1 || turn_ <= size_t(numTurns_);
 }
 
+player_info read_player(const game_data& data, const config* cfg)
+{
+  player_info res;
+
+  res.gold = atoi((*cfg)["gold"].c_str());
+
+  const config::child_list& units = cfg->get_children("unit");
+  for(config::child_list::const_iterator i = units.begin(); i != units.end(); 
++i) {
+       res.available_units.push_back(unit(data,**i));
+  }
+
+  res.can_recruit.clear();
+
+  const std::string& can_recruit_str = (*cfg)["can_recruit"];
+  if(can_recruit_str != "") {
+       const std::vector<std::string> can_recruit = 
config::split(can_recruit_str);
+       
std::copy(can_recruit.begin(),can_recruit.end(),std::inserter(res.can_recruit,res.can_recruit.end()));
+  }
+
+  return res;
+}
+
 game_state read_game(const game_data& data, const config* cfg)
 {
        log_scope("read_game");
        game_state res;
        res.label = (*cfg)["label"];
        res.version = (*cfg)["version"];
-       res.gold = atoi((*cfg)["gold"].c_str());
        res.scenario = (*cfg)["scenario"];
 
+       const config::child_list& players = cfg->get_children("player");
+
+       if(players.size()==0) {
+               std::cerr << "WARNING: no players found, old save file?" << 
std::endl;
+       } else {
+               for(config::child_list::const_iterator i = players.begin(); i 
!= players.end(); ++i) {
+                       std::string save_id=(**i)["save_id"];
+
+                       if(save_id.empty()) {
+                               std::cerr << "Corrupted player entry: NULL 
save_id" << std::endl;
+                       } else {
+                               player_info player=read_player(data, *i);
+                               res.players.insert(std::pair<std::string, 
player_info>(save_id,player));
+                       }
+               }
+       }
+
        std::cerr << "scenario: '" << res.scenario << "'\n";
 
        res.difficulty = (*cfg)["difficulty"];
@@ -213,11 +251,6 @@
        if(res.campaign_type.empty())
                res.campaign_type = "scenario";
 
-       const config::child_list& units = cfg->get_children("unit");
-       for(config::child_list::const_iterator i = units.begin(); i != 
units.end(); ++i) {
-               res.available_units.push_back(unit(data,**i));
-       }
-
        const config* const vars = cfg->child("variables");
        if(vars != NULL) {
                res.variables = *vars;
@@ -244,14 +277,6 @@
                res.starting_pos = *replay_start;
        }
 
-       res.can_recruit.clear();
-
-       const std::string& can_recruit_str = (*cfg)["can_recruit"];
-       if(can_recruit_str != "") {
-               const std::vector<std::string> can_recruit = 
config::split(can_recruit_str);
-               
std::copy(can_recruit.begin(),can_recruit.end(),std::inserter(res.can_recruit,res.can_recruit.end()));
-       }
-
        if(cfg->child("statistics")) {
                statistics::fresh_stats();
                statistics::read_stats(*cfg->child("statistics"));
@@ -260,16 +285,38 @@
        return res;
 }
 
+void write_player(const player_info& player, config& cfg)
+{
+       char buf[50];
+       sprintf(buf,"%d",player.gold);
+
+       cfg["gold"] = buf;
+
+       for(std::vector<unit>::const_iterator i = 
player.available_units.begin();
+           i != player.available_units.end(); ++i) {
+               config new_cfg;
+               i->write(new_cfg);
+               cfg.add_child("unit",new_cfg);
+       }
+
+       std::stringstream can_recruit;
+       
std::copy(player.can_recruit.begin(),player.can_recruit.end(),std::ostream_iterator<std::string>(can_recruit,","));
+       std::string can_recruit_str = can_recruit.str();
+
+       //remove the trailing comma
+       if(can_recruit_str.empty() == false) {
+               can_recruit_str.resize(can_recruit_str.size()-1);
+       }
+
+       cfg["can_recruit"] = can_recruit_str;
+}
+
 void write_game(const game_state& game, config& cfg, WRITE_GAME_MODE mode)
 {
        log_scope("write_game");
        cfg["label"] = game.label;
        cfg["version"] = game_config::version;
 
-       char buf[50];
-       sprintf(buf,"%d",game.gold);
-       cfg["gold"] = buf;
-
        cfg["scenario"] = game.scenario;
 
        cfg["campaign_type"] = game.campaign_type;
@@ -280,11 +327,12 @@
 
        cfg.add_child("variables",game.variables);
 
-       for(std::vector<unit>::const_iterator i = game.available_units.begin();
-           i != game.available_units.end(); ++i) {
+       for(std::map<std::string, player_info>::const_iterator 
i=game.players.begin();
+           i!=game.players.end(); ++i) {
                config new_cfg;
-               i->write(new_cfg);
-               cfg.add_child("unit",new_cfg);
+               write_player(i->second, new_cfg);
+               new_cfg["save_id"]=i->first;
+               cfg.add_child("player", new_cfg);
        }
 
        if(mode == WRITE_FULL_GAME) {
@@ -296,16 +344,6 @@
                cfg.add_child("replay_start",game.starting_pos);
                cfg.add_child("statistics",statistics::write_stats());
        }
-
-       std::stringstream can_recruit;
-       
std::copy(game.can_recruit.begin(),game.can_recruit.end(),std::ostream_iterator<std::string>(can_recruit,","));
-       std::string can_recruit_str = can_recruit.str();
-
-       //remove the trailing comma
-       if(can_recruit_str.size() > 0)
-               can_recruit_str.resize(can_recruit_str.size()-1);
-
-       cfg["can_recruit"] = can_recruit_str;
 }
 
 //a structure for comparing to save_info objects based on their modified time.
@@ -482,11 +520,17 @@
        }
 
        //find the first human leader so we can display their icon in the load 
menu
+
+       //ideally we should grab all leaders if there's more than 1
+       //human player?
        std::string leader;
-       
-       for(std::vector<unit>::const_iterator u = 
state.available_units.begin(); u != state.available_units.end(); ++u) {
-               if(u->can_recruit()) {
-                       leader = u->type().name();
+
+       for(std::map<std::string, player_info>::const_iterator p = 
state.players.begin();
+           p!=state.players.end(); ++p) {
+               for(std::vector<unit>::const_iterator u = 
p->second.available_units.begin(); u != p->second.available_units.end(); ++u) {
+                       if(u->can_recruit()) {
+                               leader = u->type().name();
+                       }
                }
        }
 
Index: wesnoth/src/gamestatus.hpp
diff -u wesnoth/src/gamestatus.hpp:1.30 wesnoth/src/gamestatus.hpp:1.31
--- wesnoth/src/gamestatus.hpp:1.30     Thu Jun 10 23:43:25 2004
+++ wesnoth/src/gamestatus.hpp  Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: gamestatus.hpp,v 1.30 2004/06/10 23:43:25 Sirp Exp $ */
+/* $Id: gamestatus.hpp,v 1.31 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -114,24 +114,51 @@
        int numTurns_;
 };
 
+// Information on a particular player of the game.
+struct player_info
+{
+  player_info():gold(-1) {}
+
+  int gold; //amount of gold the player has saved
+  std::vector<unit> available_units; //units the player may recall
+
+  std::set<std::string> can_recruit; //units the player has the ability to 
recruit
+};
+
 //object which holds all the data needed to start a scenario.
 //i.e. this is the object serialized to disk when saving/loading a game.
 //is also the object which needs to be created to start a nwe game
 struct game_state
 {
-       game_state() : gold(-1), difficulty("NORMAL") {}
+       game_state() : difficulty("NORMAL") {}
        std::string label; //name of the game (e.g. name of save file)
        std::string version; //version game was created with.
        std::string campaign_type; //type of the game - campaign, multiplayer 
etc
+
+       std::string campaign_define; //if there is a define the campaign uses 
to customize data
+
        std::string scenario; //the scenario being played
-       int gold; //amount of gold the player has saved
-       std::vector<unit> available_units; //units the player may recall
-       config variables; //variables that have been set
-       std::string difficulty; //the difficulty level the game is being played 
on.
 
-       std::set<std::string> can_recruit; //units the player has the ability 
to recruit
+       // information about campaign players who carry resources from
+       // previous levels, indexed by a string identifier (which is
+       // the leader name by default, but can be set with the "id"
+       // attribute of the "side" tag)
+       std::map<std::string, player_info> players;
+
+       // Return the Nth player, or NULL if no such player exists
+       player_info* get_player(std::string id) {
+         std::map<std::string, player_info>::iterator found=players.find(id);
+
+         if(found==players.end()) {
+           std::cerr << "WARNING: player " << id << " does not exist." << 
std::endl;
+           return NULL;
+         } else {
+           return &found->second;
+         }
+       }
 
-       std::string campaign_define; //if there is a define the campaign uses 
to customize data
+       config variables; //variables that have been set
+       std::string difficulty; //the difficulty level the game is being played 
on.
 
        //if the game is saved mid-level, we have a series of replay steps to
        //take the game up to the position it was saved at.
Index: wesnoth/src/multiplayer.cpp
diff -u wesnoth/src/multiplayer.cpp:1.118 wesnoth/src/multiplayer.cpp:1.119
--- wesnoth/src/multiplayer.cpp:1.118   Sat Aug 28 04:51:51 2004
+++ wesnoth/src/multiplayer.cpp Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: multiplayer.cpp,v 1.118 2004/08/28 04:51:51 Sirp Exp $ */
+/* $Id: multiplayer.cpp,v 1.119 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -64,9 +64,12 @@
 {
        std::cerr << "setup dialog ctor\n";
 
-       state_.available_units.clear();
+        for(std::map<std::string, player_info>::iterator 
i=state_.players.begin();
+            i!=state_.players.end(); ++i) {
+          i->second.available_units.clear();
+          i->second.can_recruit.clear();
+        }
        state_.variables.clear();
-       state_.can_recruit.clear();
 
        //build the list of scenarios to play
        get_files_in_dir(get_user_data_dir() + 
"/editor/maps",&user_maps_,NULL,FILE_NAME_ONLY);
Index: wesnoth/src/multiplayer_client.cpp
diff -u wesnoth/src/multiplayer_client.cpp:1.62 
wesnoth/src/multiplayer_client.cpp:1.63
--- wesnoth/src/multiplayer_client.cpp:1.62     Sun Aug 29 11:12:20 2004
+++ wesnoth/src/multiplayer_client.cpp  Mon Sep 13 03:16:19 2004
@@ -523,7 +523,11 @@
 
                state.starting_pos = sides;
                state.snapshot = sides;
-               state.can_recruit.clear();
+
+                for(std::map<std::string, player_info>::iterator 
i=state.players.begin();
+                    i!=state.players.end(); ++i) {
+                  i->second.can_recruit.clear();
+                }
     
                recorder.set_save_info(state);
     
Index: wesnoth/src/multiplayer_connect.cpp
diff -u wesnoth/src/multiplayer_connect.cpp:1.64 
wesnoth/src/multiplayer_connect.cpp:1.65
--- wesnoth/src/multiplayer_connect.cpp:1.64    Sun Aug 29 23:28:26 2004
+++ wesnoth/src/multiplayer_connect.cpp Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: multiplayer_connect.cpp,v 1.64 2004/08/29 23:28:26 Sirp Exp $ */
+/* $Id: multiplayer_connect.cpp,v 1.65 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -89,8 +89,10 @@
 
                load_game(*data_, game, *state_);
 
-               state_->available_units.clear();
-               state_->can_recruit.clear();
+               for(std::map<std::string, player_info>::iterator i = 
state_->players.begin(); i != state_->players.end(); ++i) {
+                       i->second.available_units.clear();
+                       i->second.can_recruit.clear();
+               }
 
                if(state_->campaign_type != "multiplayer") {
                        gui::show_dialog(*disp_, NULL, "", 
@@ -112,8 +114,7 @@
                level_ptr = &scenario_data;
 
                //make all sides untaken
-               for(config::child_itors i = level_ptr->child_range("side");
-                   i.first != i.second; ++i.first) {
+               for(config::child_itors i = level_ptr->child_range("side"); 
i.first != i.second; ++i.first) {
                        (**i.first)["taken"] = "";
 
                        //tell clients not to change their race
@@ -155,7 +156,10 @@
 
        level_ = level_ptr;
        state_->label = level_->values["name"];
-       state_->gold = -10000;
+
+       for(std::map<std::string, player_info>::iterator i = 
state_->players.begin(); i != state_->players.end(); ++i) {
+               i->second.gold = -10000;
+       }
 
        state_->scenario = scenario_data["id"];
 
@@ -271,8 +275,7 @@
 
        const config::child_list& possible_sides = 
era_cfg->get_children("multiplayer_side");
 
-       for(std::vector<config*>::const_iterator race = possible_sides.begin();
-           race != possible_sides.end(); ++race) {
+       for(std::vector<config*>::const_iterator race = possible_sides.begin(); 
race != possible_sides.end(); ++race) {
                player_races_.push_back((**race)["name"]);
        }
 
@@ -777,7 +780,10 @@
        //it was just there to tell clients about the replay data
        level_->clear_children("replay");
        std::vector<config*> story;
-       state_->can_recruit.clear();
+       for(std::map<std::string, player_info>::iterator i = 
state_->players.begin(); i != state_->players.end(); ++i) {
+               i->second.can_recruit.clear();
+       }
+
        play_level(*data_, *cfg_, level_, disp_->video(), *state_, story);
        recorder.clear();
 
@@ -801,8 +807,7 @@
 
 void mp_connect::update_network()
 {
-       for(std::map<config*,network::connection>::const_iterator i = 
positions_.begin();
-           i != positions_.end(); ++i) {
+       for(std::map<config*,network::connection>::const_iterator i = 
positions_.begin(); i != positions_.end(); ++i) {
                if(!i->second) {
                        //We are waiting on someone
                        network::connection sock = network::accept_connection();
@@ -836,8 +841,7 @@
                bool changes = false;
 
                //a socket has disconnected. Remove its positions.
-               for(std::map<config*,network::connection>::iterator i = 
positions_.begin();
-                   i != positions_.end(); ++i) {
+               for(std::map<config*,network::connection>::iterator i = 
positions_.begin(); i != positions_.end(); ++i) {
                        if(i->second == e.socket) {
                                changes = true;
                                i->second = 0;
Index: wesnoth/src/playlevel.cpp
diff -u wesnoth/src/playlevel.cpp:1.152 wesnoth/src/playlevel.cpp:1.153
--- wesnoth/src/playlevel.cpp:1.152     Sat Sep 11 21:22:57 2004
+++ wesnoth/src/playlevel.cpp   Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: playlevel.cpp,v 1.152 2004/09/11 21:22:57 gruikya Exp $ */
+/* $Id: playlevel.cpp,v 1.153 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -88,8 +88,7 @@
                std::set<int> placed;
                std::set<gamemap::location> positions_taken;
 
-               for(std::vector<placing_info>::const_iterator i = 
placings.begin();
-                   i != placings.end() && placed.size() != sides.size(); ++i) {
+               for(std::vector<placing_info>::const_iterator i = 
placings.begin(); i != placings.end() && placed.size() != sides.size(); ++i) {
                        if(placed.count(i->side) == 0 && 
positions_taken.count(i->pos) == 0) {
                                placed.insert(i->side);
                                positions_taken.insert(i->pos);
@@ -189,6 +188,24 @@
        std::cerr << (SDL_GetTicks() - ticks) << "\n";
 
        for(config::child_list::const_iterator ui = unit_cfg.begin(); ui != 
unit_cfg.end(); ++ui) {
+               std::string save_id = (**ui)["save_id"];
+
+               if(save_id.empty()) {
+                       save_id=(**ui)["description"];
+               }
+
+               player_info *player = NULL;
+
+               if((**ui)["controller"] == "human" ||
+                  (**ui)["controller"] == "network" ||
+                  (**ui)["persistent"] == "1") {
+                       player = state_of_game.get_player(save_id);
+
+                       if(!player && !save_id.empty()) {
+                               player=&state_of_game.players[save_id];
+                       }
+               }
+
                std::cerr << "initializing team...\n";
 
                if(first_human_team == -1 && (**ui)["controller"] == "human") {
@@ -202,8 +219,8 @@
                std::cerr << "found gold: '" << gold << "'\n";
 
                int ngold = lexical_cast_default<int>(gold);
-               if(ui == unit_cfg.begin() && state_of_game.gold >= ngold) {
-                       ngold = state_of_game.gold;
+               if(player && player->gold >= ngold) {
+                       ngold = player->gold;
                }
 
                std::cerr << "set gold to '" << ngold << "'\n";
@@ -216,12 +233,11 @@
 
                        //search the recall list for leader units, and if there 
is
                        //one, use it in place of the config-described unit
-                       if(ui == unit_cfg.begin()) {
-                               for(std::vector<unit>::iterator it = 
state_of_game.available_units.begin();
-                                       it != 
state_of_game.available_units.end(); ++it) {
+                       if(player) {
+                               for(std::vector<unit>::iterator it = 
player->available_units.begin(); it != player->available_units.end(); ++it) {
                                        if(it->can_recruit()) {
                                                new_unit = *it;
-                                               
state_of_game.available_units.erase(it);
+                                               
player->available_units.erase(it);
                                                break;
                                        }
                                }
@@ -253,19 +269,18 @@
 
                //if the game state specifies units that can be recruited for 
the player
                //then add them
-               if(teams.size() == 1 && state_of_game.can_recruit.empty() == 
false) {
-                       
std::copy(state_of_game.can_recruit.begin(),state_of_game.can_recruit.end(),
-                               
std::inserter(teams.back().recruits(),teams.back().recruits().end()));
+               if(player && player->can_recruit.empty() == false) {
+                       
std::copy(player->can_recruit.begin(),player->can_recruit.end(),
+                       
std::inserter(teams.back().recruits(),teams.back().recruits().end()));
                }
                
-               if(teams.size() == 1) {
-                       state_of_game.can_recruit = teams.back().recruits();
+               if(player) {
+                       player->can_recruit = teams.back().recruits();
                }
                
                //if there are additional starting units on this side
                const config::child_list& starting_units = 
(*ui)->get_children("unit");
-               for(config::child_list::const_iterator su = 
starting_units.begin();
-                   su != starting_units.end(); ++su) {
+               for(config::child_list::const_iterator su = 
starting_units.begin(); su != starting_units.end(); ++su) {
                        unit new_unit(gameinfo,**su);
 
                        
new_unit.set_side(lexical_cast_default<int>((**ui)["side"],1));
@@ -275,7 +290,9 @@
 
                        const gamemap::location loc(**su);
                        if(x.empty() || y.empty() || !map.on_board(loc)) {
-                               
state_of_game.available_units.push_back(new_unit);
+                               if(player) {
+                                       
player->available_units.push_back(new_unit);
+                               }
                        } else {
                                
units.insert(std::pair<gamemap::location,unit>(loc,new_unit));
                                std::cerr << "inserting unit for side " << 
new_unit.side() << "\n";
@@ -312,9 +329,10 @@
        }
 
        // Add all units that are recallable as encountred units.
-       for(std::vector<unit>::iterator help_recall_it = 
state_of_game.available_units.begin();
-               help_recall_it != state_of_game.available_units.end(); 
help_recall_it++) {
-               
preferences::encountered_units().insert(help_recall_it->type().name());
+       for(std::map<std::string, player_info>::iterator pi = 
state_of_game.players.begin(); pi!=state_of_game.players.end(); ++pi) {
+               for(std::vector<unit>::iterator help_recall_it = 
pi->second.available_units.begin(); help_recall_it != 
pi->second.available_units.end(); help_recall_it++) {
+                       
preferences::encountered_units().insert(help_recall_it->type().name());
+               }
        }
 
        // Add all terrains on the map as encountered terrains.
@@ -360,8 +378,7 @@
                                            state_of_game,status,gameinfo);
 
        if(recorder.skipping() == false) {
-               for(std::vector<config*>::const_iterator story_i = 
story.begin();
-                   story_i != story.end(); ++story_i) {
+               for(std::vector<config*>::const_iterator story_i = 
story.begin(); story_i != story.end(); ++story_i) {
                        show_intro(gui,**story_i, *level);
                }
        }
@@ -463,8 +480,7 @@
 
                        std::cerr << "turn: " << turn++ << "\n";
 
-                       for(std::vector<team>::iterator team_it = 
teams.begin()+first_player;
-                           team_it != teams.end(); ++team_it) {
+                       for(std::vector<team>::iterator team_it = 
teams.begin()+first_player; team_it != teams.end(); ++team_it) {
                                log_scope("player turn");
                                player_number = (team_it - teams.begin()) + 1;
 
@@ -695,50 +711,76 @@
 
                        //add all the units that survived the scenario
                        for(std::map<gamemap::location,unit>::iterator un = 
units.begin(); un != units.end(); ++un) {
-                               if(un->second.side() == 1) {
+                               player_info 
*player=state_of_game.get_player(teams[un->second.side()-1].save_id());
+
+                               if(player) {
                                        un->second.new_turn();
                                        un->second.new_level();
-                                       
state_of_game.available_units.push_back(un->second);
+                                       
player->available_units.push_back(un->second);
                                }
                        }
 
                        //'continue' is like a victory, except it doesn't 
announce victory,
                        //and the player returns 100% of gold.
                        if(end_level.result == LEVEL_CONTINUE || 
end_level.result == LEVEL_CONTINUE_NO_SAVE) {
-                               state_of_game.gold = teams[0].gold();
+                               for(std::vector<team>::iterator 
i=teams.begin(); i!=teams.end(); ++i) {
+                                       player_info 
*player=state_of_game.get_player(i->save_id());
+                                       if(player) {
+                                               player->gold = i->gold();
+                                       }
+                               }
+
                                return end_level.result == 
LEVEL_CONTINUE_NO_SAVE ? LEVEL_CONTINUE_NO_SAVE : VICTORY;
                        }
 
-                       const int remaining_gold = teams[0].gold();
-                       const int finishing_bonus_per_turn = 
map.villages().size()*game_config::village_income + game_config::base_income;
-                       const int turns_left = 
maximum<int>(0,status.number_of_turns() - status.turn());
-                       const int finishing_bonus = end_level.gold_bonus ?
-                                     (finishing_bonus_per_turn * turns_left) : 
0;
-                       state_of_game.gold = 
((remaining_gold+finishing_bonus)*80)/100;
+
+                       std::stringstream report;
+
+                       for(std::vector<team>::iterator i=teams.begin(); 
i!=teams.end(); ++i) {
+                               player_info 
*player=state_of_game.get_player(i->save_id());
+
+                               const int remaining_gold = i->gold();
+                               const int finishing_bonus_per_turn = 
map.villages().size()*game_config::village_income + game_config::base_income;
+                               const int turns_left = 
maximum<int>(0,status.number_of_turns() - status.turn());
+                               const int finishing_bonus = 
end_level.gold_bonus ?
+                                            (finishing_bonus_per_turn * 
turns_left) : 0;
+
+                               if(player) {
+                                       player->gold = 
((remaining_gold+finishing_bonus)*80)/100;
+
+                                       if(state_of_game.players.size()>1) {
+                                               if(i!=teams.begin()) {
+                                                       report << "\n";
+                                               }
+
+                                               report << i->save_id() << ": " 
<< "\n";
+                                       }
+
+                                       report << _("Remaining gold") << ": "
+                                              << remaining_gold << "\n";
+                                       if(end_level.gold_bonus) {
+                                               report << _("Early finish 
bonus") << ": "
+                                                      << 
finishing_bonus_per_turn
+                                                      << " " << _("per turn") 
<< "\n"
+                                                      << _("Turns finished 
early") << ": "
+                                                      << turns_left << "\n"
+                                                      << _("Bonus") << ": "
+                                                      << finishing_bonus << 
"\n"
+                                                      << _("Gold") << ": "
+                                                      << 
(remaining_gold+finishing_bonus);
+                                       }
+
+                                       // xgettext:no-c-format
+                                       report << "\n" << _("80% of gold is 
retained for the next scenario") << "\n" << _("Retained Gold") << ": " << 
player->gold;
+                               }
+                       }
 
                        gui::show_dialog(gui,NULL,_("Victory"),
                                         _("You have emerged 
victorious!"),gui::OK_ONLY);
-                       std::stringstream report;
-                       report << _("Remaining gold") << ": "
-                              << remaining_gold << "\n";
-                       if(end_level.gold_bonus) {
-                               report << _("Early finish bonus") << ": "
-                                      << finishing_bonus_per_turn
-                                          << " " << _("per turn") << "\n"
-                                      << _("Turns finished early") << ": "
-                                      << turns_left << "\n"
-                                      << _("Bonus") << ": "
-                                          << finishing_bonus << "\n"
-                                      << _("Gold") << ": "
-                                          << (remaining_gold+finishing_bonus);
-                       }
-
-                       // xgettext:no-c-format
-                       report << "\n" << _("80% of gold is retained for the 
next scenario") << "\n"
-                                  << _("Retained Gold") << ": "
-                                  << state_of_game.gold;
 
-                       gui::show_dialog(gui,NULL,"",report.str(),gui::OK_ONLY);
+                       if(state_of_game.players.size()>0) {
+                               
gui::show_dialog(gui,NULL,"",report.str(),gui::OK_ONLY);
+                       }
                        return VICTORY;
                }
        } //end catch
Index: wesnoth/src/playturn.cpp
diff -u wesnoth/src/playturn.cpp:1.263 wesnoth/src/playturn.cpp:1.264
--- wesnoth/src/playturn.cpp:1.263      Sat Sep 11 02:55:46 2004
+++ wesnoth/src/playturn.cpp    Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: playturn.cpp,v 1.263 2004/09/11 02:55:46 Sirp Exp $ */
+/* $Id: playturn.cpp,v 1.264 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -97,8 +97,7 @@
                        gotos.push_back(ui->first);
        }
 
-       for(std::vector<gamemap::location>::const_iterator g = gotos.begin();
-           g != gotos.end(); ++g) {
+       for(std::vector<gamemap::location>::const_iterator g = gotos.begin(); g 
!= gotos.end(); ++g) {
                unit_map::const_iterator ui = units.find(*g);
                turn_data.move_unit_to_loc(ui,ui->second.get_goto(),false);
        }
@@ -426,16 +425,15 @@
                        }
                }
        } else if(is_middle_click(event) && event.state == SDL_PRESSED) {
-         // clicked on a hex on the minimap? then initiate minimap scrolling
-         const gamemap::location& loc = 
gui_.minimap_location_on(event.x,event.y);
-         minimap_scrolling_ = false;
-         if(loc.valid()) {
-           minimap_scrolling_ = true;
-           last_hex_ = loc;
-           gui_.scroll_to_tile(loc.x,loc.y,display::WARP,false);
-           return;
-         }
-         else {
+               // clicked on a hex on the minimap? then initiate minimap 
scrolling
+               const gamemap::location& loc = 
gui_.minimap_location_on(event.x,event.y);
+               minimap_scrolling_ = false;
+               if(loc.valid()) {
+                       minimap_scrolling_ = true;
+                       last_hex_ = loc;
+                       gui_.scroll_to_tile(loc.x,loc.y,display::WARP,false);
+                       return;
+               } else {
                const SDL_Rect& rect = gui_.map_area();
                const int centerx = (rect.x + rect.w)/2;
                const int centery = (rect.y + rect.h)/2;
@@ -444,7 +442,7 @@
                const int ydisp = event.y - centery;
 
                gui_.scroll(xdisp,ydisp);
-         }
+               }
        } else if(event.button == SDL_BUTTON_WHEELUP ||
                  event.button == SDL_BUTTON_WHEELDOWN) {
                const int speed = preferences::scroll_speed() *
@@ -545,8 +543,7 @@
 
        //if the unit is selected and then itself clicked on,
        //any goto command is cancelled
-       if(u != units_.end() && !browse_ &&
-          selected_hex_ == hex && u->second.side() == team_num_) {
+       if(u != units_.end() && !browse_ && selected_hex_ == hex && 
u->second.side() == team_num_) {
                u->second.set_goto(gamemap::location());
        }
 
@@ -670,8 +667,7 @@
                        u = units_.find(selected_hex_);
                        enemy = units_.find(hex);
 
-                       if(u == units_.end() || enemy == units_.end() ||
-                          size_t(res) >= attacks.size()) {
+                       if(u == units_.end() || enemy == units_.end() || 
size_t(res) >= attacks.size()) {
                                return;
                        }
 
@@ -683,8 +679,7 @@
                        recorder.add_attack(selected_hex_,hex,res);
 
                        try {
-                               
attack(gui_,map_,teams_,selected_hex_,hex,res,units_,
-                                      status_,gameinfo_,true);
+                               
attack(gui_,map_,teams_,selected_hex_,hex,res,units_,status_,gameinfo_,true);
                        } catch(end_level_exception&) {
                                //if the level ends due to a unit being killed, 
still see if
                                //either the attacker or defender should advance
@@ -1056,10 +1051,7 @@
 
 bool turn_info::unit_in_cycle(unit_map::const_iterator it) const
 {
-       if(it->second.side() == team_num_ &&
-          unit_can_move(it->first,units_,map_,teams_) &&
-          it->second.user_end_turn() == false &&
-          !gui_.fogged(it->first.x,it->first.y)) {
+       if(it->second.side() == team_num_ && 
unit_can_move(it->first,units_,map_,teams_) && it->second.user_end_turn() == 
false && !gui_.fogged(it->first.x,it->first.y)) {
                const bool is_enemy = 
current_team().is_enemy(int(gui_.viewing_team()+1));
                return is_enemy == false || 
it->second.invisible(map_.underlying_terrain(it->first),status_.get_time_of_day().lawful_bonus,it->first,units_,teams_)
 == false;
        }
@@ -1092,8 +1084,7 @@
        if(it != units_.end() && !gui_.fogged(it->first.x,it->first.y)) {
                const bool ignore_zocs = it->second.type().is_skirmisher();
                const bool teleport = it->second.type().teleports();
-               current_paths_ = paths(map_,status_,gameinfo_,units_,
-                              
it->first,teams_,ignore_zocs,teleport,path_turns_);
+               current_paths_ = 
paths(map_,status_,gameinfo_,units_,it->first,teams_,ignore_zocs,teleport,path_turns_);
                gui_.set_paths(&current_paths_);
 
                gui_.scroll_to_tile(it->first.x,it->first.y,display::WARP);
@@ -1187,8 +1178,7 @@
                return;
 
        const unit_map::iterator un = units_.find(selected_hex_);
-       if(un != units_.end() && un->second.side() == team_num_ &&
-          un->second.movement_left() >= 0) {
+       if(un != units_.end() && un->second.side() == team_num_ && 
un->second.movement_left() >= 0) {
                un->second.set_user_end_turn(!un->second.user_end_turn());
                gui_.draw_tile(selected_hex_.x,selected_hex_.y);
 
@@ -1209,16 +1199,23 @@
        const command_disabler disable_commands(&gui_);
 
        undo_action& action = undo_stack_.back();
-       if (action.is_recall()) {
-               // Undo a recall action
-               team& current_team = teams_[team_num_-1];
-               const unit& un = units_.find(action.recall_loc)->second;
-               statistics::un_recall_unit(un);
-               current_team.spend_gold(-game_config::recall_cost);
-               std::vector<unit>& recall_list = state_of_game_.available_units;
-               recall_list.insert(recall_list.begin()+action.recall_pos,un);
-               units_.erase(action.recall_loc);
-               gui_.draw_tile(action.recall_loc.x,action.recall_loc.y);
+       if(action.is_recall()) {
+               player_info 
*player=state_of_game_.get_player(teams_[team_num_-1].save_id());
+
+               if(!player) {
+                       std::cerr << "WARNING: trying to undo a recall for side 
" << team_num_ << ", which has no recall list!" << std::endl;
+               } else {
+                       // Undo a recall action
+                       team& current_team = teams_[team_num_-1];
+                       const unit& un = units_.find(action.recall_loc)->second;
+                       statistics::un_recall_unit(un);
+                       current_team.spend_gold(-game_config::recall_cost);
+
+                       std::vector<unit>& recall_list = 
player->available_units;
+                       
recall_list.insert(recall_list.begin()+action.recall_pos,un);
+                       units_.erase(action.recall_loc);
+                       gui_.draw_tile(action.recall_loc.x,action.recall_loc.y);
+               }
        } else {
                // Undo a move action
                const int starting_moves = action.starting_moves;
@@ -1285,18 +1282,23 @@
        gui_.set_route(NULL);
 
        undo_action& action = redo_stack_.back();
-       if (action.is_recall()) {
-               // Redo recall
-               std::vector<unit>& recall_list = state_of_game_.available_units;
-               unit& un = recall_list[action.recall_pos];
-               recruit_unit(map_,team_num_,units_,un,action.recall_loc,&gui_);
-               statistics::recall_unit(un);
-               team& current_team = teams_[team_num_-1];
-               current_team.spend_gold(game_config::recall_cost);
-               recall_list.erase(recall_list.begin()+action.recall_pos);
-               recorder.add_recall(action.recall_pos,action.recall_loc);
+       if(action.is_recall()) {
+               player_info 
*player=state_of_game_.get_player(teams_[team_num_-1].save_id());
+               if(!player) {
+                       std::cerr << "WARNING: trying to redo a recall for side 
" << team_num_ << ", which has no recall list!" << std::endl;
+               } else {
+                       // Redo recall
+                       std::vector<unit>& recall_list = 
player->available_units;
+                       unit& un = recall_list[action.recall_pos];
+                       
recruit_unit(map_,team_num_,units_,un,action.recall_loc,&gui_);
+                       statistics::recall_unit(un);
+                       team& current_team = teams_[team_num_-1];
+                       current_team.spend_gold(game_config::recall_cost);
+                       
recall_list.erase(recall_list.begin()+action.recall_pos);
+                       
recorder.add_recall(action.recall_pos,action.recall_loc);
 
-               gui_.draw_tile(action.recall_loc.x,action.recall_loc.y);
+                       gui_.draw_tile(action.recall_loc.x,action.recall_loc.y);
+               }
        } else {
                // Redo movement action
                const int starting_moves = action.starting_moves;
@@ -1488,8 +1490,7 @@
                sprintf(buf,"%d",side_num);
                side["side"] = buf;
 
-               for(std::map<gamemap::location,unit>::const_iterator i = 
units_.begin();
-                   i != units_.end(); ++i) {
+               for(std::map<gamemap::location,unit>::const_iterator i = 
units_.begin(); i != units_.end(); ++i) {
                        if(i->second.side() == side_num) {
                                config& u = side.add_child("unit");
                                i->first.write(u);
@@ -1595,8 +1596,7 @@
        std::vector<std::string> item_keys;
        std::vector<std::string> items;
        const std::set<std::string>& recruits = current_team.recruits();
-       for(std::set<std::string>::const_iterator it =
-           recruits.begin(); it != recruits.end(); ++it) {
+       for(std::set<std::string>::const_iterator it = recruits.begin(); it != 
recruits.end(); ++it) {
                item_keys.push_back(*it);
                const std::map<std::string,unit_type>::const_iterator
                                u_type = gameinfo_.unit_types.find(*it);
@@ -1749,8 +1749,14 @@
        if(browse_)
                return;
 
+       player_info *player = 
state_of_game_.get_player(teams_[team_num_-1].save_id());
+       if(!player) {
+               std::cerr << "WARNING: cannot recall a unit for side " << 
team_num_ << ", which has no recall list!" << std::endl;
+               return;
+       }
+
        team& current_team = teams_[team_num_-1];
-       std::vector<unit>& recall_list = state_of_game_.available_units;
+       std::vector<unit>& recall_list = player->available_units;
 
        //sort the available units into order by value
        //so that the most valuable units are shown first
@@ -1881,8 +1887,7 @@
 {
        std::vector<std::string> options;
        std::vector<unit> unit_choices;
-       for(game_data::unit_type_map::const_iterator i = 
gameinfo_.unit_types.begin();
-           i != gameinfo_.unit_types.end(); ++i) {
+       for(game_data::unit_type_map::const_iterator i = 
gameinfo_.unit_types.begin(); i != gameinfo_.unit_types.end(); ++i) {
                options.push_back(i->first);
                unit_choices.push_back(unit(&i->second,1,false));
                unit_choices.back().new_turn();
@@ -2125,7 +2130,7 @@
 
 void turn_info::user_command()
 {
-  create_textbox(floating_textbox::TEXTBOX_COMMAND,_("prompt^Command:"));
+       create_textbox(floating_textbox::TEXTBOX_COMMAND,_("prompt^Command:"));
 }
 
 void turn_info::show_help()
Index: wesnoth/src/publish_campaign.cpp
diff -u wesnoth/src/publish_campaign.cpp:1.1 
wesnoth/src/publish_campaign.cpp:1.2
--- wesnoth/src/publish_campaign.cpp:1.1        Sun Sep 12 21:55:20 2004
+++ wesnoth/src/publish_campaign.cpp    Mon Sep 13 03:16:19 2004
@@ -7,6 +7,12 @@
 
 namespace {
 const std::string campaign_dir = get_user_data_dir() + "/data/campaigns";
+void setup_dirs()
+{
+       make_directory(get_user_data_dir() + "/data");
+       make_directory(campaign_dir);
+}
+
 }
 
 std::vector<std::string> available_campaigns()
@@ -125,6 +131,7 @@
 
 void unarchive_campaign(const config& cfg)
 {
+       setup_dirs();
        unarchive_dir(campaign_dir,cfg);
 }
 
Index: wesnoth/src/replay.cpp
diff -u wesnoth/src/replay.cpp:1.79 wesnoth/src/replay.cpp:1.80
--- wesnoth/src/replay.cpp:1.79 Sun Aug 29 11:48:34 2004
+++ wesnoth/src/replay.cpp      Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: replay.cpp,v 1.79 2004/08/29 11:48:34 isaaccp Exp $ */
+/* $Id: replay.cpp,v 1.80 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -292,8 +292,7 @@
        random_ = NULL;
 }
 
-void replay::add_attack(const gamemap::location& a, const gamemap::location& b,
-                        int weapon)
+void replay::add_attack(const gamemap::location& a, const gamemap::location& 
b, int weapon)
 {
        add_pos("attack",a,b);
        char buf[100];
@@ -540,8 +539,7 @@
 
 void replay::add_config(const config& cfg, MARK_SENT mark)
 {
-       for(config::const_child_itors i = cfg.child_range("command");
-           i.first != i.second; ++i.first) {
+       for(config::const_child_itors i = cfg.child_range("command"); i.first 
!= i.second; ++i.first) {
                config& cfg = cfg_.add_child("command",**i.first);
                if(mark == MARK_AS_SENT) {
                        cfg["sent"] = "yes";
@@ -716,19 +714,23 @@
                }
 
                else if((child = cfg->child("recall")) != NULL) {
-                       std::sort(state_of_game.available_units.begin(),
-                                 state_of_game.available_units.end(),
-                                 compare_unit_values());
+                       player_info 
*player=state_of_game.get_player(teams[team_num].save_id());
+                       if(!player) {
+                               std::cerr << "illegal recall\n";
+                               throw replay::error();
+                       }
+
+                       
std::sort(player->available_units.begin(),player->available_units.end(),compare_unit_values());
 
                        const std::string recall_num = (*child)["value"];
                        const int val = atoi(recall_num.c_str());
 
                        gamemap::location loc(*child);
 
-                       if(val >= 0 && val < 
int(state_of_game.available_units.size())) {
-                               
statistics::recall_unit(state_of_game.available_units[val]);
-                               
recruit_unit(map,team_num,units,state_of_game.available_units[val],loc);
-                               
state_of_game.available_units.erase(state_of_game.available_units.begin()+val);
+                       if(val >= 0 && val < 
int(player->available_units.size())) {
+                               
statistics::recall_unit(player->available_units[val]);
+                               
recruit_unit(map,team_num,units,player->available_units[val],loc);
+                               
player->available_units.erase(player->available_units.begin()+val);
                                
current_team.spend_gold(game_config::recall_cost);
                        } else {
                                std::cerr << "illegal recall\n";
Index: wesnoth/src/team.cpp
diff -u wesnoth/src/team.cpp:1.70 wesnoth/src/team.cpp:1.71
--- wesnoth/src/team.cpp:1.70   Sun Aug 29 11:12:20 2004
+++ wesnoth/src/team.cpp        Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: team.cpp,v 1.70 2004/08/29 11:12:20 isaaccp Exp $ */
+/* $Id: team.cpp,v 1.71 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -63,8 +63,15 @@
        income = cfg["income"];
        name = cfg["name"];
        team_name = cfg["team_name"];
-       if(team_name.empty())
+       if(team_name.empty()) {
                team_name = cfg["side"];
+       }
+
+       save_id = cfg["save_id"];
+       if(save_id.empty()) {
+               save_id = cfg["description"];
+       }
+
        colour = lexical_cast_default<int>(cfg["colour"],-1);
        if(colour == -1)
                colour = lexical_cast_default<int>(cfg["side"],-1);
@@ -82,8 +89,7 @@
        const std::string& enemies_list = cfg["enemy"];
        if(!enemies_list.empty()) {
                std::vector<std::string> venemies = config::split(enemies_list);
-               for(std::vector<std::string>::const_iterator i = 
venemies.begin();
-                   i != venemies.end(); ++i) {
+               for(std::vector<std::string>::const_iterator i = 
venemies.begin(); i != venemies.end(); ++i) {
                        enemies.push_back(atoi(i->c_str()));
                }
        }
@@ -188,6 +194,7 @@
        cfg["income"] = income;
        cfg["name"] = name;
        cfg["team_name"] = team_name;
+       cfg["save_id"] = save_id;
        cfg["flag"] = flag;
        cfg["description"] = description;
 
@@ -327,8 +334,7 @@
 
 int team::income() const
 {
-       return atoi(info_.income.c_str()) +
-              
villages_.size()*info_.income_per_village+game_config::base_income;
+       return atoi(info_.income.c_str()) + 
villages_.size()*info_.income_per_village+game_config::base_income;
 }
 
 void team::new_turn()
@@ -487,6 +493,11 @@
        info_.team_name = name;
 }
 
+const std::string& team::save_id() const
+{
+       return info_.save_id;
+}
+
 const std::string& team::flag() const
 {
        return info_.flag;
Index: wesnoth/src/team.hpp
diff -u wesnoth/src/team.hpp:1.49 wesnoth/src/team.hpp:1.50
--- wesnoth/src/team.hpp:1.49   Sun Aug 22 01:30:07 2004
+++ wesnoth/src/team.hpp        Mon Sep 13 03:16:19 2004
@@ -1,4 +1,4 @@
-/* $Id: team.hpp,v 1.49 2004/08/22 01:30:07 Sirp Exp $ */
+/* $Id: team.hpp,v 1.50 2004/09/13 03:16:19 Sirp Exp $ */
 /*
    Copyright (C) 2003 by David White <address@hidden>
    Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -68,6 +68,7 @@
                std::vector<std::string> recruitment_pattern;
                std::vector<int> enemies;
                std::string team_name;
+               std::string save_id;
 
                std::string flag;
 
@@ -113,6 +114,7 @@
        std::set<std::string>& recruits();
        const std::vector<std::string>& recruitment_pattern() const;
        const std::string& name() const;
+       const std::string& save_id() const;
 
        bool is_enemy(int n) const {
                const size_t index = size_t(n-1);
@@ -160,7 +162,7 @@
        bool fog_or_shroud() const { return uses_shroud() || uses_fog(); }
        bool clear_shroud(int x, int y) { return shroud_.clear(x+1,y+1); }
        void place_shroud(int x, int y) { shroud_.place(x+1,y+1); }
-       bool clear_fog(int x, int y)  { return fog_.clear(x+1,y+1); }
+       bool clear_fog(int x, int y) { return fog_.clear(x+1,y+1); }
        void refog() { fog_.reset(); }
        
        bool knows_about_team(size_t index) const;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]