initial commit, lordsawar source, slightly modified
[lordsawar] / src / gui / history-report-dialog.cpp
diff --git a/src/gui/history-report-dialog.cpp b/src/gui/history-report-dialog.cpp
new file mode 100644 (file)
index 0000000..a746be5
--- /dev/null
@@ -0,0 +1,926 @@
+//  Copyright (C) 2007, 2008, 2009 Ben Asselstine
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU Library General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
+//  02110-1301, USA.
+
+#include <config.h>
+
+#include <gtkmm.h>
+#include <sigc++/functors/mem_fun.h>
+
+#include "history-report-dialog.h"
+
+#include "glade-helpers.h"
+#include "image-helpers.h"
+#include "input-helpers.h"
+#include "line-chart.h"
+#include "report-dialog.h"
+#include "ucompose.hpp"
+#include "defs.h"
+#include "File.h"
+#include "GameMap.h"
+#include "citylist.h"
+#include "ruinlist.h"
+#include "city.h"
+#include "ruin.h"
+#include "playerlist.h"
+#include "history.h"
+#include "network-history.h"
+#include "GraphicsCache.h"
+#include "boxcompose.h"
+
+HistoryReportDialog::HistoryReportDialog(Player *p, HistoryReportType type)
+{
+  d_player = p;
+  Glib::RefPtr<Gtk::Builder> xml
+    = Gtk::Builder::create_from_file(get_glade_path()
+                               + "/history-report-dialog.ui");
+
+  xml->get_widget("dialog", dialog);
+  decorate(dialog);
+
+  generatePastCitylists();
+  generatePastRuinlists();
+  generatePastEventlists();
+
+  xml->get_widget("map_image", map_image);
+  historymap = new HistoryMap(Citylist::getInstance(), Ruinlist::getInstance());
+  historymap->map_changed.connect
+    (sigc::mem_fun(this, &HistoryReportDialog::on_map_changed));
+
+  xml->get_widget("turn_scale", turn_scale);
+  set_title(_("History"));
+  turn_scale->set_range(1, past_citylists.size());
+  turn_scale->set_value(past_citylists.size());
+
+  turn_scale->signal_value_changed().connect
+    (sigc::bind(sigc::mem_fun(this, &HistoryReportDialog::on_turn_changed),
+               turn_scale));
+
+  xml->get_widget("history_notebook", history_notebook);
+  history_notebook->set_current_page(type);
+  history_notebook->signal_switch_page().connect(
+       sigc::mem_fun(*this, &HistoryReportDialog::on_switch_page));
+
+  xml->get_widget("city_label", city_label);
+  xml->get_widget("ruin_label", ruin_label);
+  xml->get_widget("gold_label", gold_label);
+  xml->get_widget("winner_label", winner_label);
+
+  //events_list = Gtk::ListStore::create(events_columns);
+  //xml->get_widget("treeview", events_treeview);
+  //events_treeview->set_model(events_list);
+  //events_treeview->append_column("", events_columns.box);
+  //events_treeview->append_column("", events_columns.desc);
+
+  xml->get_widget("events_list_box", events_list_box);
+  Gtk::Button *close_button;
+  xml->get_widget("close_button", close_button);
+  close_button->signal_clicked().connect
+    (sigc::mem_fun(*this, &HistoryReportDialog::on_close_button));
+  closing = false;
+
+  xml->get_widget("city_alignment", city_alignment);
+  xml->get_widget("ruin_alignment", ruin_alignment);
+  xml->get_widget("gold_alignment", gold_alignment);
+  xml->get_widget("winner_alignment", winner_alignment);
+
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  Gdk::Color colour;
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      colour = (*pit)->getColor();
+      if (*pit == d_player)
+       d_colours.push_front(colour);
+      else
+       d_colours.push_back(colour);
+    }
+
+  generatePastCityCounts();
+  city_chart = new LineChart(past_citycounts, d_colours, 
+                            Citylist::getInstance()->size(),
+                            _("Cities"), _("Turns"));
+  city_alignment->add(*manage(city_chart));
+
+  generatePastRuinCounts();
+  ruin_chart = new LineChart(past_ruincounts, d_colours, 
+                            Ruinlist::getInstance()->size(),
+                            _("Explored Ruins"), _("Turns"));
+  ruin_alignment->add(*manage(ruin_chart));
+
+  generatePastGoldCounts();
+  gold_chart = new LineChart(past_goldcounts, d_colours, 0, 
+                            _("Gold Pieces"), _("Turns"));
+  gold_alignment->add(*manage(gold_chart));
+
+  generatePastWinningCounts();
+  rank_chart = new LineChart(past_rankcounts, d_colours, 100,
+                            _("Score"), _("Turns"));
+  winner_alignment->add(*manage(rank_chart));
+
+  fill_in_turn_info((guint32)turn_scale->get_value());
+}
+
+HistoryReportDialog::~HistoryReportDialog()
+{
+  std::vector<std::list<NetworkHistory *> >::iterator it;
+  it = past_eventlists.begin();
+  for (; it != past_eventlists.end(); it++)
+    {
+      std::list<NetworkHistory*> hist = (*it);
+      std::list<NetworkHistory*>::iterator hit = hist.begin();
+      for (; hit != hist.end(); hit++)
+       delete (*hit);
+    }
+  delete dialog;
+  delete historymap;
+}
+
+void HistoryReportDialog::generatePastEventlists()
+{
+  bool last_turn = false;
+  std::list<NetworkHistory*> *elist = new std::list<NetworkHistory*>();
+
+  //keep a set of pointers to remember how far we are into each player's history
+  std::list<History*> *hist[MAX_PLAYERS];
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hist[(*pit)->getId()] = (*pit)->getHistorylist();
+    }
+  std::list<History*>::iterator hit[MAX_PLAYERS];
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hit[(*pit)->getId()] = hist[(*pit)->getId()]->begin();
+    }
+
+  unsigned int count = 0;
+  while (1)
+    {
+      //now we see what cities we took this turn
+      pit = Playerlist::getInstance()->begin();
+      for (; pit != Playerlist::getInstance()->end(); ++pit)
+       {
+         if (*pit == Playerlist::getInstance()->getNeutral())
+           continue;
+         //dump everything up to the next turn
+         guint32 id = (*pit)->getId();
+         if (hit[id] == hist[id]->end())
+           continue;
+         for (; hit[id] != hist[id]->end(); ++hit[id])
+           {
+             if ((*hit[id])->getType() == History::START_TURN)
+               {
+                 hit[id]++;
+                 break;
+               }
+             switch ((*hit[id])->getType())
+               {
+               case History::FOUND_SAGE: 
+               case History::HERO_EMERGES:
+               case History::HERO_QUEST_STARTED:
+               case History::HERO_QUEST_COMPLETED:
+               case History::HERO_KILLED_IN_CITY:
+               case History::HERO_KILLED_IN_BATTLE:
+               case History::HERO_KILLED_SEARCHING:
+               case History::HERO_CITY_WON:
+               case History::HERO_FINDS_ALLIES:
+               case History::PLAYER_VANQUISHED:
+               case History::DIPLOMATIC_TREACHERY:
+               case History::DIPLOMATIC_WAR:
+               case History::DIPLOMATIC_PEACE:
+               case History::HERO_RUIN_EXPLORED:
+                 elist->push_back(new NetworkHistory(*hit[id], (*pit)->getId()));
+                 break;
+               case History::START_TURN:
+               case History::GOLD_TOTAL:
+               case History::CITY_WON:
+               case History::CITY_RAZED:
+               case History::SCORE:
+               case History::HERO_REWARD_RUIN:
+               case History::END_TURN:
+                 break;
+               }
+           }
+         if (hit[id] == hist[id]->end())
+           {
+             count++;
+             if (count == Playerlist::getInstance()->size() - 2)
+               last_turn = true;
+           }
+       }
+      //and add it to the list
+      past_eventlists.push_back(*elist);
+      std::list<NetworkHistory*> *new_elist = new std::list<NetworkHistory*>();
+      elist = new_elist;
+      if (last_turn == true)
+       break;
+
+    }
+}
+
+void HistoryReportDialog::generatePastCitylists()
+{
+  bool last_turn = false;
+
+  //keep a set of pointers to remember how far we are into each player's history
+  std::list<History*> *hist[MAX_PLAYERS];
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hist[(*pit)->getId()] = (*pit)->getHistorylist();
+    }
+  std::list<History*>::iterator hit[MAX_PLAYERS];
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hit[(*pit)->getId()] = hist[(*pit)->getId()]->begin();
+    }
+
+  //start off with an initial city list where all cities are neutral owned
+  LocationList<City*> *clist = new LocationList<City*>();
+  Citylist *cl = Citylist::getInstance();
+  for (Citylist::iterator it = cl->begin(); it != cl->end(); ++it)
+    clist->push_back(new City(**it));
+  for (LocationList<City*>::iterator it = clist->begin(); it != clist->end(); ++it)
+    {
+      (*it)->setOwner(Playerlist::getInstance()->getNeutral());
+      //is the city burned to begin with?
+      bool no_city_history = true;
+      pit = Playerlist::getInstance()->begin();
+      for (; pit != Playerlist::getInstance()->end(); ++pit)
+       if ((*pit)->conqueredCity(*it) == true)
+         no_city_history = false;
+      if ((*it)->isBurnt() == true && no_city_history)
+       (*it)->setBurnt(true);
+      else
+       (*it)->setBurnt(false);
+    }
+
+  unsigned int count = 0;
+  while (1)
+    {
+      //now we see what cities we took this turn
+      pit = Playerlist::getInstance()->begin();
+      for (; pit != Playerlist::getInstance()->end(); ++pit)
+       {
+         if (*pit == Playerlist::getInstance()->getNeutral())
+           continue;
+         //dump everything up to the next turn
+         guint32 id = (*pit)->getId();
+         if (hit[id] == hist[id]->end())
+           continue;
+         for (; hit[id] != hist[id]->end(); hit[id]++)
+           {
+             if ((*hit[id])->getType() == History::START_TURN)
+               {
+                 hit[id]++;
+                 break;
+               }
+             else if ((*hit[id])->getType() == History::CITY_WON)
+               {
+                 guint32 city_id;
+                 city_id = dynamic_cast<History_CityWon*>(*hit[id])->getCityId();
+                 //find city with this city id in clist
+                 LocationList<City*>::iterator cit = clist->begin();
+                 for (; cit != clist->end(); ++cit)
+                   if ((*cit)->getId() == city_id)
+                     {
+                       (*cit)->setOwner(*pit);
+                       break;
+                     }
+               }
+             else if ((*hit[id])->getType() == History::CITY_RAZED)
+               {
+                 guint32 city_id;
+                 city_id = dynamic_cast<History_CityRazed*>(*hit[id])->getCityId();
+                 //find city with this city id in clist
+                 LocationList<City*>::iterator cit = clist->begin();
+                 for (; cit != clist->end(); ++cit)
+                   if ((*cit)->getId() == city_id)
+                     {
+                       //change the owner to neutral 
+                       (*cit)->setOwner(Playerlist::getInstance()->getNeutral());
+                       (*cit)->setBurnt(true);
+                       break;
+                     }
+               }
+           }
+         if (hit[id] == hist[id]->end())
+           {
+             count++;
+             if (count == Playerlist::getInstance()->size() - 2)
+               last_turn = true;
+           }
+       }
+      //and add it to the list
+      past_citylists.push_back(clist);
+      LocationList<City*> *new_clist = new LocationList<City*>();
+      for (LocationList<City*>::iterator it = clist->begin(); 
+          it != clist->end(); ++it)
+       new_clist->push_back(new City(**it));
+      clist = new_clist;
+      if (last_turn == true)
+       break;
+
+    }
+  past_citylists.erase(--past_citylists.end());
+}
+
+void HistoryReportDialog::set_parent_window(Gtk::Window &parent)
+{
+  dialog->set_transient_for(parent);
+  //dialog->set_position(Gtk::WIN_POS_CENTER_ON_PARENT);
+}
+
+void HistoryReportDialog::hide()
+{
+  dialog->hide();
+}
+
+void HistoryReportDialog::run()
+{
+  historymap->resize();
+  historymap->draw(Playerlist::getActiveplayer());
+
+  dialog->show_all();
+  dialog->run();
+}
+
+void HistoryReportDialog::on_map_changed(Glib::RefPtr<Gdk::Pixmap> map)
+{
+  map_image->property_pixmap() = map;
+}
+
+void HistoryReportDialog::on_turn_changed(Gtk::Scale *scale)
+{
+  //tell the historymap to show another set of cities
+  guint32 turn = (guint32)turn_scale->get_value();
+  if (turn > past_citylists.size() - 1)
+    historymap->updateCities(Citylist::getInstance(), Ruinlist::getInstance());
+  else
+    historymap->updateCities(past_citylists[turn], past_ruinlists[turn]);
+  city_chart->set_x_indicator(turn);
+  ruin_chart->set_x_indicator(turn);
+  gold_chart->set_x_indicator(turn);
+  rank_chart->set_x_indicator(turn);
+  fill_in_turn_info(turn);
+}
+
+void HistoryReportDialog::update_window_title()
+{
+  switch (history_notebook->get_current_page())
+    {
+    case CITY:
+      set_title(_("City History"));
+      break;
+    case RUIN:
+      set_title(_("Ruin History"));
+      break;
+    case EVENTS: 
+      set_title(_("Event History"));
+      break;
+    case GOLD: 
+      set_title(_("Gold History"));
+      break;
+    case WINNING:
+      set_title(_("Winner History"));
+      break;
+    }
+}
+
+void HistoryReportDialog::fill_in_turn_info(guint32 turn)
+{
+  Glib::ustring s;
+  guint32 count;
+  update_window_title();
+
+  //update the event list
+  //events_list->clear();
+  events_list_box->children().erase(events_list_box->children().begin(),
+                                    events_list_box->children().end());
+  if (turn <= past_eventlists.size() - 1)
+    {
+      std::list<NetworkHistory*> hist = past_eventlists[turn];
+      std::list<NetworkHistory*>::iterator hit = hist.begin();
+      for (; hit != hist.end(); hit++)
+       addHistoryEvent(*hit);
+    }
+
+  //update the gold chart
+  //on turn # you had # gold pieces
+  std::list<guint32> goldlist = *past_goldcounts.begin();
+  std::list<guint32>::iterator it = goldlist.begin();
+  count=1;
+  for (; it != goldlist.end(); it++, count++)
+    {
+      if (count == turn)
+       {
+         count = *it;
+         break;
+       }
+    }
+  turn == past_citylists.size() ?
+    s = String::ucompose(ngettext("On turn %1 you have %2 gold piece!",
+                                 "On turn %1 you have %2 gold pieces!",
+                                 count), turn, count) :
+    s = String::ucompose(ngettext("On turn %1 you had %2 gold piece!",
+                                 "On turn %1 you had %2 gold pieces!",
+                                 count), turn, count);
+  gold_label->set_text(s);
+
+  //update the city chart
+  std::list<guint32> citylist = *past_citycounts.begin();
+  it = citylist.begin();
+  count = 0;
+  for (; it != citylist.end(); it++, count++)
+    {
+      if (count == turn)
+       {
+         count = *it;
+         break;
+       }
+    }
+  turn == past_citylists.size() ?
+    s = String::ucompose(ngettext("On turn %1 you have %2 city!",
+                                 "On turn %1 you have %2 cities!",
+                                 count), turn, count) :
+    s = String::ucompose(ngettext("On turn %1 you had %2 city!",
+                                 "On turn %1 you had %2 cities!",
+                                 count), turn, count);
+  city_label->set_text(s);
+
+  //update the ruin chart
+  std::list<guint32> ruinlist = *past_ruincounts.begin();
+  it = ruinlist.begin();
+  count = 0;
+  for (; it != ruinlist.end(); it++, count++)
+    {
+      if (count == turn)
+       {
+         count = *it;
+         break;
+       }
+    }
+  turn == past_ruinlists.size() ?
+  s = String::ucompose(ngettext("By turn %1 you explored %2 ruin!",
+                                "By turn %1 you explored %2 ruins!",
+                                count), turn, count) :
+  s = String::ucompose(ngettext("By turn %1 you explored %2 ruin!",
+                                "By turn %1 you explored %2 ruins!",
+                                count), turn, count);
+  ruin_label->set_text(s);
+
+  //on turn # you were coming #
+  std::list<guint32> scores;
+  std::list<std::list<guint32> >::iterator rit = past_rankcounts.begin();
+  for (; rit != past_rankcounts.end(); rit++)
+    {
+      it = (*rit).begin();
+      count=1;
+      for (; it != (*rit).end(); it++, count++)
+       {
+         if (count == turn)
+           {
+             count = *it;
+             scores.push_back(*it);
+             break;
+           }
+       }
+    }
+  turn == past_citylists.size() ?
+    s = String::ucompose(_("On turn %1 you are coming %2!"),
+                        turn, ReportDialog::calculateRank(scores, *scores.begin())):
+    s = String::ucompose(_("On turn %1 you were coming %2!"),
+                        turn, ReportDialog::calculateRank(scores, *scores.begin()));
+  winner_label->set_text(s);
+}
+
+void HistoryReportDialog::on_switch_page(GtkNotebookPage *page, guint number)
+{
+  if (closing)
+    return;
+  update_window_title();
+}
+
+void HistoryReportDialog::addHistoryEvent(NetworkHistory *event)
+{
+  GraphicsCache *gc = GraphicsCache::getInstance();
+  Playerlist *pl = Playerlist::getInstance();
+  Player *p = event->getOwner();
+
+  History *history = event->getHistory();
+
+  Gtk::HBox *box = NULL;
+
+                              
+  Glib::RefPtr<Gdk::Pixbuf> shield = gc->getShieldPic(1, p)->to_pixbuf();
+  switch (history->getType())
+    {
+    case History::FOUND_SAGE: 
+       {
+         History_FoundSage *ev = static_cast<History_FoundSage *>(history);
+          box = Box::ucompose(_("%1 %2 finds a sage!"), shield,
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_EMERGES:
+       {
+         History_HeroEmerges *ev;
+         ev = static_cast<History_HeroEmerges *>(history);
+          box = Box::ucompose(_("%1 %2 emerges in %3"), shield,
+                              ev->getHeroName(), ev->getCityName());
+         break;
+       }
+    case History::HERO_QUEST_STARTED:
+       {
+         History_HeroQuestStarted *ev = 
+            static_cast<History_HeroQuestStarted*>(history);
+          box = Box::ucompose(_("%1 %2 begins a quest!"), shield,
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_QUEST_COMPLETED:
+       {
+         History_HeroQuestCompleted *ev
+            = static_cast<History_HeroQuestCompleted *>(history);
+          box = Box::ucompose(_("%1 %2 finishes a quest!"), shield,
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_KILLED_IN_CITY:
+       {
+         History_HeroKilledInCity *ev = 
+            static_cast<History_HeroKilledInCity *>(history);
+          box = Box::ucompose(_("%1 %2 is killed in %3!"), shield,
+                              ev->getHeroName(), ev->getCityName());
+         break;
+       }
+    case History::HERO_KILLED_IN_BATTLE:
+       {
+         History_HeroKilledInBattle *ev = 
+            static_cast<History_HeroKilledInBattle *>(history);
+          box = Box::ucompose(_("%1 %2 is killed in battle!"), shield,
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_KILLED_SEARCHING:
+       {
+         History_HeroKilledSearching *ev = 
+            static_cast<History_HeroKilledSearching *>(history);
+          box = Box::ucompose(_("%1 %2 is killed while searching!"), shield,
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_CITY_WON:
+       {
+         History_HeroCityWon *ev = 
+            static_cast<History_HeroCityWon *>(history);
+          box = Box::ucompose(_("%1 %2 conquers %3!"), shield,
+                              ev->getHeroName(), ev->getCityName());
+         break;
+       }
+    case History::PLAYER_VANQUISHED:
+       {
+          box = Box::ucompose(_("%1 %2 utterly vanquished!"), shield,
+                              p->getName());
+         break;
+       }
+    case History::DIPLOMATIC_PEACE:
+       {
+         History_DiplomacyPeace *ev = 
+            static_cast<History_DiplomacyPeace*>(history);
+         Player *opponent = pl->getPlayer(ev->getOpponentId());
+          box = Box::ucompose(_("%1 %2 at peace with %3 %4!"), shield,
+                              p->getName(), 
+                              gc->getShieldPic(1, opponent)->to_pixbuf(), 
+                              opponent->getName());
+         break;
+       }
+    case History::DIPLOMATIC_WAR:
+       {
+         History_DiplomacyWar *ev = 
+            static_cast<History_DiplomacyWar*>(history);
+         Player *opponent = pl->getPlayer(ev->getOpponentId());
+          box = Box::ucompose(_("%1 %2 at war with %3 %4!"), shield,
+                              p->getName(), 
+                              gc->getShieldPic(1, opponent)->to_pixbuf(), 
+                              opponent->getName());
+         break;
+       }
+    case History::DIPLOMATIC_TREACHERY:
+       {
+         History_DiplomacyTreachery *ev = 
+            static_cast<History_DiplomacyTreachery*>(history);
+         Player *opponent = pl->getPlayer(ev->getOpponentId());
+          box = Box::ucompose(_("%1 Treachery on %2 %3!"), shield,
+                              gc->getShieldPic(1, opponent)->to_pixbuf(), 
+                              opponent->getName());
+         break;
+       }
+    case History::HERO_FINDS_ALLIES:
+       {
+         History_HeroFindsAllies *ev = 
+            static_cast<History_HeroFindsAllies*>(history);
+          box = Box::ucompose(_("%1 %2 finds allies!"), shield, 
+                              ev->getHeroName());
+         break;
+       }
+    case History::HERO_RUIN_EXPLORED:
+       {
+         History_HeroRuinExplored *ev = 
+            static_cast<History_HeroRuinExplored *>(history);
+          Ruinlist *rl = Ruinlist::getInstance();
+          box = Box::ucompose(_("%1 %2 explores %3!"), shield, 
+                              ev->getHeroName(),
+                              rl->getById(ev->getRuinId())->getName());
+         break;
+       }
+    default:
+      box = NULL;
+      break;
+    }
+
+  if (box)
+    {
+      events_list_box->pack_start(*manage(box), Gtk::PACK_SHRINK, 0);
+      events_list_box->show_all();
+    }
+}
+void HistoryReportDialog::on_close_button()
+{
+  closing = true;
+  //FIXME: find out why the page_switch events with crap data,
+  //and then remove this function, and the closing variable too.
+}
+
+void HistoryReportDialog::generatePastWinningCounts()
+{
+  //go through the history list looking for score events, per player
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      std::list<History*> *hist = (*pit)->getHistorylist();
+      std::list<History*>::iterator hit = hist->begin();
+      std::list<guint32> line;
+      for (; hit != hist->end(); hit++)
+       {
+         if ((*hit)->getType() == History::SCORE)
+           {
+             History_Score *event = static_cast<History_Score*>(*hit);
+             line.push_back (event->getScore());
+           }
+       }
+      line.push_back ((guint32)(*pit)->getScore());
+      if (*pit == d_player)
+       past_rankcounts.push_front(line);
+      else
+       past_rankcounts.push_back(line);
+    }
+}
+
+void HistoryReportDialog::generatePastCityCounts()
+{
+  // go through the past city list
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      //go through the past city lists, searching for cities owned by this
+      //player
+
+      std::list<guint32> line;
+      for (unsigned int i = 0; i < past_citylists.size(); i++)
+       {
+         guint32 total_cities = 0;
+         LocationList<City*>::iterator it = past_citylists[i]->begin();
+         for (; it != past_citylists[i]->end(); it++)
+           {
+             if ((*it)->getOwner() == *pit)
+               total_cities++;
+           }
+         line.push_back(total_cities);
+       }
+
+      line.push_back(Citylist::getInstance()->countCities(*pit));
+      if (*pit == d_player)
+       past_citycounts.push_front(line);
+      else
+       past_citycounts.push_back(line);
+
+    }
+}
+
+void HistoryReportDialog::generatePastGoldCounts()
+{
+  //go through the history list looking for gold events, per player
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      std::list<History*> *hist = (*pit)->getHistorylist();
+      std::list<History*>::iterator hit = hist->begin();
+      std::list<guint32> line;
+      for (; hit != hist->end(); hit++)
+       {
+         if ((*hit)->getType() == History::GOLD_TOTAL)
+           {
+             History_GoldTotal *event = static_cast<History_GoldTotal*>(*hit);
+             line.push_back (event->getGold());
+           }
+       }
+      line.push_back ((guint32)(*pit)->getGold());
+      if (*pit == d_player)
+       past_goldcounts.push_front(line);
+      else
+       past_goldcounts.push_back(line);
+    }
+}
+
+void HistoryReportDialog::generatePastRuinCounts()
+{
+  //how many ruins did the players search at each turn?
+
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+        continue;
+      std::list<guint32> line;
+      for (unsigned int i = 0; i < past_citylists.size(); i++)
+        {
+          guint32 total_ruins = 0;
+          LocationList<Ruin*>::iterator it = past_ruinlists[i]->begin();
+          for (; it != past_ruinlists[i]->end(); it++)
+            {
+              Ruin *ruin = *it;
+              if (ruin->isHidden() == true && ruin->getOwner() != *pit)
+                continue;
+              if (ruin->isSearched() == true && 
+                  (*pit)->searchedRuin(ruin) == true)
+                {
+                  ruin->setOwner(*pit);
+                  total_ruins++;
+                }
+            }
+          line.push_back(total_ruins);
+        }
+      line.push_back(Ruinlist::getInstance()->countExploredRuins(*pit));
+      if (*pit == d_player)
+       past_ruincounts.push_front(line);
+      else
+       past_ruincounts.push_back(line);
+    }
+}
+
+void HistoryReportDialog::generatePastRuinlists()
+{
+  //we don't do this per player
+  //we just count how many ruins are unexplored at every turn.
+  //how do we deal with hidden ruins?
+  //they should pop up when found.
+  bool last_turn = false;
+
+  //keep a set of pointers to remember how far we are into each player's history
+  std::list<History*> *hist[MAX_PLAYERS];
+  Playerlist::iterator pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hist[(*pit)->getId()] = (*pit)->getHistorylist();
+    }
+  std::list<History*>::iterator hit[MAX_PLAYERS];
+  pit = Playerlist::getInstance()->begin();
+  for (; pit != Playerlist::getInstance()->end(); ++pit)
+    {
+      if (*pit == Playerlist::getInstance()->getNeutral())
+       continue;
+      hit[(*pit)->getId()] = hist[(*pit)->getId()]->begin();
+    }
+
+  //start off with an initial ruin list where all ruins are unexplored and hidden.
+  //all hidden ruins haven't been found yet, unless they started off that way.
+  LocationList<Ruin*> *rlist = new LocationList<Ruin*>();
+  Ruinlist *rl = Ruinlist::getInstance();
+  for (Ruinlist::iterator it = rl->begin(); it != rl->end(); ++it)
+    rlist->push_back(new Ruin(**it));
+  for (LocationList<Ruin*>::iterator it = rlist->begin(); it != rlist->end(); ++it)
+    {
+      //is the ruin searched to begin with?
+      bool no_ruin_history = true;
+      pit = Playerlist::getInstance()->begin();
+      for (; pit != Playerlist::getInstance()->end(); ++pit)
+       if ((*pit)->searchedRuin(*it) == true)
+         no_ruin_history = false;
+      if ((*it)->isSearched() == true && no_ruin_history)
+        (*it)->setSearched(true);
+      else
+        {
+          (*it)->setSearched(false);
+          if ((*it)->isHidden())
+            (*it)->setOwner(NULL);
+        }
+    }
+
+  unsigned int count = 0;
+  while (1)
+    {
+      //now we see what ruins we took this turn
+      pit = Playerlist::getInstance()->begin();
+      for (; pit != Playerlist::getInstance()->end(); ++pit)
+       {
+         if (*pit == Playerlist::getInstance()->getNeutral())
+           continue;
+         //dump everything up to the next turn
+         guint32 id = (*pit)->getId();
+         if (hit[id] == hist[id]->end())
+           continue;
+         for (; hit[id] != hist[id]->end(); hit[id]++)
+           {
+             if ((*hit[id])->getType() == History::START_TURN)
+               {
+                 hit[id]++;
+                 break;
+               }
+              //when a ruin becomes visible all of a sudden, we mark it as visible
+             else if ((*hit[id])->getType() == History::HERO_REWARD_RUIN)
+                {
+                 guint32 ruin_id;
+                 ruin_id = 
+                    dynamic_cast<History_HeroRewardRuin*>(*hit[id])->getRuinId();
+                 //find ruin with this ruin id in rlist
+                 LocationList<Ruin*>::iterator rit = rlist->begin();
+                 for (; rit != rlist->end(); ++rit)
+                   if ((*rit)->getId() == ruin_id)
+                     {
+                        (*rit)->setOwner(*pit);
+                       break;
+                     }
+                }
+             else if ((*hit[id])->getType() == History::HERO_RUIN_EXPLORED)
+               {
+                 guint32 ruin_id;
+                 ruin_id = 
+                    dynamic_cast<History_HeroRuinExplored*>(*hit[id])->getRuinId();
+                 //find ruin with this ruin id in rlist
+                 LocationList<Ruin*>::iterator rit = rlist->begin();
+                 for (; rit != rlist->end(); ++rit)
+                   if ((*rit)->getId() == ruin_id)
+                     {
+                       (*rit)->setSearched(true);
+                       break;
+                     }
+               }
+           }
+         if (hit[id] == hist[id]->end())
+           {
+             count++;
+             if (count == Playerlist::getInstance()->size() - 2)
+               last_turn = true;
+           }
+       }
+      //and add it to the list
+      past_ruinlists.push_back(rlist);
+      LocationList<Ruin*> *new_rlist = new LocationList<Ruin*>();
+      for (LocationList<Ruin*>::iterator it = rlist->begin(); 
+          it != rlist->end(); ++it)
+       new_rlist->push_back(new Ruin(**it));
+      rlist = new_rlist;
+      if (last_turn == true)
+       break;
+
+    }
+  past_ruinlists.erase(--past_ruinlists.end());
+}