initial commit, lordsawar source, slightly modified
[lordsawar] / src / game.cpp
1 // Copyright (C) 2006, 2007, 2008, 2009 Ben Asselstine
2 // Copyright (C) 2007, 2008 Ole Laursen
3 //
4 //  This program is free software; you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation; either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU Library General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
17 //  02110-1301, USA.
18
19 #include "config.h"
20
21 #include <algorithm>
22 #include <vector>
23 #include <assert.h>
24 #include <gtkmm.h>
25 #include <sigc++/functors/mem_fun.h>
26 #include <sigc++/adaptors/bind.h>
27
28 #include "game.h"
29
30 #include "ucompose.hpp"
31 #include "rectangle.h"
32 #include "sound.h"
33 #include "GraphicsCache.h"
34 #include "GameScenario.h"
35 #include "NextTurnNetworked.h"
36 #include "NextTurnHotseat.h"
37 #include "NextTurnPbm.h"
38
39 #include "gamebigmap.h"
40 #include "smallmap.h"
41
42 #include "army.h"
43 #include "fight.h"
44 #include "hero.h"
45 #include "heroproto.h"
46 #include "stacklist.h"
47 #include "citylist.h"
48 #include "ruinlist.h"
49 #include "templelist.h"
50 #include "signpostlist.h"
51 #include "city.h"
52 #include "ruin.h"
53 #include "signpost.h"
54 #include "temple.h"
55 #include "GameMap.h"
56 #include "playerlist.h"
57 #include "path.h"
58 #include "Configuration.h"
59 #include "File.h"
60 #include "Quest.h"
61 #include "reward.h"
62 #include "action.h"
63 #include "game-parameters.h"
64 #include "FogMap.h"
65 #include "GameMap.h"
66 #include "history.h"
67 #include "pbm-game-server.h"
68 #include "LocationBox.h"
69 #include "Backpack.h"
70 #include "MapBackpack.h"
71 #include "stacktile.h"
72
73 #include "herotemplates.h"
74 #include "GameScenarioOptions.h"
75 #include "ai_fast.h"
76 #include "ai_smart.h"
77 #include "Sage.h"
78 #include "Commentator.h"
79
80 Game *Game::current_game = 0;
81
82 //#define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl;}
83 #define debug(x)
84 void Game::addPlayer(Player *p)
85 {
86
87   //disconnect prior players' connections
88   for (std::list<sigc::connection>::iterator it = 
89        connections[p->getId()].begin(); 
90        it != connections[p->getId()].end(); it++) 
91     (*it).disconnect();
92   connections[p->getId()].clear();
93
94   //now setup the connections that are specific for human players
95   if (p->getType() == Player::HUMAN)
96     {
97       connections[p->getId()].push_back
98         (p->sheroGainsLevel.connect(sigc::mem_fun(this, &Game::heroGainsLevel)));
99       connections[p->getId()].push_back
100         (p->snewMedalArmy.connect(sigc::mem_fun(this, &Game::newMedalArmy)));
101
102       connections[p->getId()].push_back
103         (p->streachery.connect
104          (sigc::bind<0>
105           (sigc::mem_fun
106            (stack_considers_treachery, 
107             &sigc::signal<bool, Player *, Stack *, Player *, Vector<int> >::emit), p)));
108       connections[p->getId()].push_back
109         (p->hero_arrives_with_allies.connect
110          (sigc::mem_fun
111           (hero_arrives, &sigc::signal<void, int>::emit)));
112       connections[p->getId()].push_back
113         (p->advice_asked.connect
114          (sigc::mem_fun(advice_asked, &sigc::signal<void, float>::emit)));
115       connections[p->getId()].push_back
116         (p->shaltedStack.connect
117          (sigc::mem_fun(this, &Game::on_stack_halted)));
118       connections[p->getId()].push_back
119         (p->getStacklist()->sgrouped.connect
120          (sigc::mem_fun(this, &Game::on_stack_grouped)));
121     }
122       
123       
124   //now do all of the common connections
125       
126   connections[p->getId()].push_back
127     (p->getStacklist()->snewpos.connect
128      (sigc::mem_fun(stack_moves, &sigc::signal<void, Stack*, Vector<int> >::emit)));
129   connections[p->getId()].push_back
130     (p->srecruitingHero.connect(sigc::mem_fun(this, &Game::recruitHero)));
131   connections[p->getId()].push_back
132     (p->svisitingTemple.connect
133      (sigc::mem_fun(this, &Game::stack_searches_temple)));
134   connections[p->getId()].push_back
135     (p->ssearchingRuin.connect
136      (sigc::mem_fun(this, &Game::stack_searches_ruin)));
137   connections[p->getId()].push_back
138     (p->getStacklist()->snewpos.connect
139      (sigc::mem_fun(this, &Game::stack_arrives_on_tile)));
140   connections[p->getId()].push_back
141     (p->getStacklist()->soldpos.connect
142      (sigc::mem_fun(this, &Game::stack_leaves_tile)));
143   connections[p->getId()].push_back
144     (p->aborted_turn.connect (sigc::mem_fun
145            (game_stopped, &sigc::signal<void>::emit)));
146
147   connections[p->getId()].push_back
148     (p->schangingStats.connect 
149      (sigc::mem_fun(this, &Game::update_sidebar_stats)));
150         
151   connections[p->getId()].push_back
152     (p->schangingStatus.connect 
153          (sigc::mem_fun(progress_status_changed, &sigc::signal<void, std::string>::emit)));
154         
155   connections[p->getId()].push_back
156     (p->sbusy.connect (sigc::mem_fun (progress_changed, 
157                                       &sigc::signal<void>::emit)));
158   connections[p->getId()].push_back
159     (p->supdatingStack.connect (sigc::mem_fun(this, &Game::stackUpdate)));
160   connections[p->getId()].push_back
161     (p->sinvadingCity.connect(sigc::mem_fun(this, &Game::invading_city)));
162   connections[p->getId()].push_back
163     (p->streacheryStack.connect(sigc::mem_fun(this, &Game::maybeTreachery)));
164   connections[p->getId()].push_back
165     (p->fight_started.connect (sigc::mem_fun(*this, &Game::on_fight_started)));
166   connections[p->getId()].push_back
167     (p->ruinfight_started.connect
168      (sigc::mem_fun
169       (ruinfight_started, &sigc::signal<void, Stack *, Stack *>::emit)));
170   connections[p->getId()].push_back
171     (p->ruinfight_finished.connect
172      (sigc::mem_fun
173       (ruinfight_finished, &sigc::signal<void, Fight::Result>::emit)));
174   connections[p->getId()].push_back
175     (p->cityfight_finished.connect (sigc::mem_fun(*this, &Game::on_city_fight_finished))); 
176   if (p->getType() == Player::NETWORKED && p == Playerlist::getActiveplayer())
177     lock_inputs();
178   if (p->getType() == Player::HUMAN && p == Playerlist::getActiveplayer())
179     unlock_inputs();
180 }
181
182 void Game::on_stack_halted(Stack *stack)
183 {
184   if (stack == NULL)
185     return;
186   bigmap->reset_path_calculator(stack);
187   //tell gamebigmap that a stack just stopped
188 }
189 void Game::on_stack_grouped(Stack *stack, bool grouped)
190 {
191   bigmap->reset_path_calculator(stack);
192   //tell gamebigmap that we just grouped/ungrouped a stack.
193   return;
194 }
195 #include "game-server.h"
196
197 Game::Game(GameScenario* gameScenario, NextTurn *nextTurn)
198     : d_gameScenario(gameScenario), d_nextTurn(nextTurn)
199 {
200     current_game = this;
201     input_locked = false;
202
203     // init the bigmap
204     bigmap.reset(new GameBigMap
205                  (GameScenario::s_intense_combat, 
206                   GameScenario::s_see_opponents_production, 
207                   GameScenario::s_see_opponents_stacks, 
208                   GameScenario::s_military_advisor));
209     bigmap->stack_selected.connect(
210         sigc::mem_fun(this, &Game::on_stack_selected));
211     bigmap->stack_grouped_or_ungrouped.connect(
212         sigc::mem_fun(this, &Game::on_stack_grouped_or_ungrouped));
213     bigmap->path_set.connect(
214         sigc::mem_fun(this, &Game::update_control_panel));
215     bigmap->city_visited.connect(
216         sigc::mem_fun(this, &Game::on_city_visited));
217     bigmap->city_queried.connect(
218         sigc::mem_fun(this, &Game::on_city_queried));
219     bigmap->city_unqueried.connect(
220         sigc::mem_fun(this, &Game::on_city_unqueried));
221     bigmap->ruin_queried.connect(
222         sigc::mem_fun(this, &Game::on_ruin_queried));
223     bigmap->signpost_queried.connect(
224         sigc::mem_fun(this, &Game::on_signpost_queried));
225     bigmap->temple_queried.connect(
226         sigc::mem_fun(this, &Game::on_temple_queried));
227     bigmap->stack_queried.connect(
228         sigc::mem_fun(this, &Game::on_stack_queried));
229     bigmap->stack_unqueried.connect(
230         sigc::mem_fun(this, &Game::on_stack_unqueried));
231
232     // init the smallmap
233     smallmap.reset(new SmallMap);
234     // pass map changes directly through 
235     smallmap->resize();
236     smallmap->map_changed.connect(
237         sigc::mem_fun(smallmap_changed,
238                       &sigc::signal<void, Glib::RefPtr<Gdk::Pixmap>, 
239                       Gdk::Rectangle>::emit));
240
241     // connect the two maps
242     bigmap->view_changed.connect(
243         sigc::mem_fun(smallmap.get(), &SmallMap::set_view));
244     bigmap->map_changed.connect(
245         sigc::mem_fun(bigmap_changed,
246                       &sigc::signal<void, Glib::RefPtr<Gdk::Pixmap> >::emit));
247     smallmap->view_changed.connect(
248         sigc::mem_fun(bigmap.get(), &GameBigMap::set_view));
249
250     // get the maps up and running
251     bigmap->screen_size_changed(Gtk::Allocation(0,0,320,200));
252
253     // connect player callbacks
254     Playerlist* pl = Playerlist::getInstance();
255     for (Playerlist::iterator i = pl->begin(); i != pl->end(); ++i)
256     {
257         Player *p = *i;
258         addPlayer(p);
259     }
260     if (gameScenario->getPlayMode() == GameScenario::HOTSEAT)
261       pl->splayerDead.connect(sigc::mem_fun(this, &Game::on_player_died));
262     pl->ssurrender.connect(sigc::mem_fun(this, &Game::on_surrender_offered));
263
264     d_nextTurn->splayerStart.connect(
265         sigc::mem_fun(this, &Game::init_turn_for_player));
266     d_nextTurn->snextRound.connect(
267         sigc::mem_fun(d_gameScenario, &GameScenario::nextRound));
268     d_nextTurn->snextRound.connect(
269         sigc::mem_fun(this, &Game::nextRound));
270     d_nextTurn->supdating.connect(
271         sigc::mem_fun(this, &Game::redraw));
272             
273
274     center_view_on_city();
275     update_control_panel();
276
277     HeroTemplates::getInstance();
278 }
279
280 Game::~Game()
281 {
282   for (unsigned int i = 0; i < MAX_PLAYERS + 1; i++)
283     {
284       for (std::list<sigc::connection>::iterator it = connections[i].begin(); 
285            it != connections[i].end(); it++) 
286         (*it).disconnect();
287       connections[i].clear();
288     }
289     delete d_gameScenario;
290     delete d_nextTurn;
291     
292     HeroTemplates::deleteInstance();
293 }
294
295 GameScenario *Game::getScenario()
296 {
297   return current_game->d_gameScenario;
298 }
299
300 void Game::end_turn()
301 {
302   //only human players hit this.
303     unselect_active_stack();
304     clear_stack_info();
305     update_control_panel();
306     lock_inputs();
307
308     bool trigger_next_remote_player = false;
309     if (d_gameScenario->getPlayMode() == GameScenario::NETWORKED &&
310         Playerlist::getActiveplayer()->getType() == Player::NETWORKED)
311       trigger_next_remote_player = true;
312     d_nextTurn->endTurn();
313     if (trigger_next_remote_player)
314       remote_next_player_turn.emit();
315 }
316
317 void Game::update_stack_info()
318 {
319     Stack* stack = Playerlist::getActiveplayer()->getActivestack();
320
321     //if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
322         //GameScenario::s_hidden_map == true)
323       //return;
324     stack_info_changed.emit(stack);
325 }
326
327 void Game::clear_stack_info()
328 {
329     stack_info_changed.emit(0);
330 }
331
332 void Game::update_sidebar_stats()
333 {
334     SidebarStats s;
335     Player *player = Playerlist::getActiveplayer();
336     if (player == Playerlist::getInstance()->getNeutral())
337       return;
338
339     s.name = player->getName();
340     s.gold = player->getGold();
341     s.income = s.cities = 0;
342     s.income = player->getIncome();
343     s.cities = Citylist::getInstance()->countCities(player);
344
345     s.units = 0;
346     s.upkeep = player->getUpkeep() + player->getCostOfUnitsProducedThisTurn();
347     Stacklist *sl = player->getStacklist();
348     for (Stacklist::iterator i = sl->begin(), iend = sl->end(); i != iend; ++i)
349       s.units += (*i)->size();
350     
351     s.turns = d_gameScenario->getRound();
352     
353     sidebar_stats_changed.emit(s);
354 }
355
356 void Game::redraw()
357 {
358     if (bigmap.get())
359       {
360         bigmap->draw(Playerlist::getViewingplayer());
361       }
362     if (smallmap.get())
363       {
364         //if (Playerlist::getActiveplayer()->getType() == Player::HUMAN ||
365             //GameScenario::s_hidden_map == false)
366         smallmap->draw(Playerlist::getActiveplayer());
367       }
368 }
369
370 void Game::select_next_movable_stack()
371 {
372   Stacklist *sl = Playerlist::getActiveplayer()->getStacklist();
373   Stack* stack = sl->getNextMovable();
374   sl->setActivestack(stack);
375   select_active_stack();
376 }
377
378 void Game::move_map_dir(int diffx, int diffy)
379 {
380   smallmap->move_map_in_dir(Vector<int>(diffx, diffy));
381 }
382
383 void Game::move_selected_stack_dir(int diffx, int diffy)
384 {
385   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
386   if (!stack)
387     return;
388   // Get rid of the old path if there is one
389   if (stack->getPath()->size())
390     stack->getPath()->clear();
391   //See if we can move there
392   Vector<int> dest = stack->getPos();
393   dest += Vector<int>(diffx, diffy);
394   int mp = stack->getPath()->calculate(stack, dest);
395   if (mp > 0)
396     move_selected_stack_along_path();
397   else
398     {
399       Playerlist::getActiveplayer()->setActivestack(0);
400       unselect_active_stack();
401     }
402 }
403
404 void Game::move_selected_stack_northwest()
405 {
406   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
407     move_selected_stack_dir(-1, -1);
408   else
409     move_map_dir(-1,-1);
410 }
411
412 void Game::move_selected_stack_north()
413 {
414   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
415     move_selected_stack_dir(0, -1);
416   else
417     move_map_dir(0, -1);
418 }
419
420 void Game::move_selected_stack_northeast()
421 {
422   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
423     move_selected_stack_dir(1, -1);
424   else
425     move_map_dir(1, -1);
426 }
427
428 void Game::move_selected_stack_east()
429 {
430   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
431     move_selected_stack_dir(1, 0);
432   else
433     move_map_dir(1, 0);
434 }
435
436 void Game::move_selected_stack_west()
437 {
438   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
439     move_selected_stack_dir(-1, 0);
440   else
441     move_map_dir(-1, 0);
442 }
443
444 void Game::move_selected_stack_southwest()
445 {
446   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
447     move_selected_stack_dir(-1, 1);
448   else
449     move_map_dir(-1, 1);
450 }
451
452 void Game::move_selected_stack_south()
453 {
454   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
455     move_selected_stack_dir(0, 1);
456   else
457     move_map_dir(0, 1);
458 }
459
460 void Game::move_selected_stack_southeast()
461 {
462   if (Playerlist::getActiveplayer()->getActivestack() != NULL)
463     move_selected_stack_dir(1, 1);
464   else
465     move_map_dir(1, 1);
466 }
467
468 void Game::move_selected_stack_along_path()
469 {
470   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
471
472   Playerlist::getActiveplayer()->stackMove(stack);
473
474   //maybe we joined another stack
475   stack = Playerlist::getActiveplayer()->getActivestack();
476   if (stack && stack->canMove() == false)
477     {
478       Playerlist::getActiveplayer()->setActivestack(0);
479       unselect_active_stack();
480     }
481 }
482
483 void Game::move_all_stacks()
484 {
485   Player *player = Playerlist::getActiveplayer();
486   Stacklist* sl = player->getStacklist();
487
488   for (Stacklist::iterator i = sl->begin(), end = sl->end(); i != end; ++i)
489     {
490       Stack &s = **i;
491       if (!(s.empty()) && !(s.getPath()->empty()) && s.enoughMoves())
492         {
493           sl->setActivestack(&s);
494           select_active_stack();
495           bool moved = player->stackMove(player->getActivestack());
496           if (!moved)
497             break;
498           i = sl->begin();
499         }
500     }
501
502   if (sl->getActivestack()->canMove() == false)
503     {
504       Playerlist::getActiveplayer()->setActivestack(0);
505       unselect_active_stack();
506     }
507 }
508
509 void Game::defend_selected_stack()
510 {
511   Player *player = Playerlist::getActiveplayer();
512   Stack *stack = player->getActivestack();
513   assert(stack);
514
515   stack->setDefending(true);
516
517   stack = player->getStacklist()->getNextMovable();
518   player->setActivestack(stack);
519
520   if (stack)
521     select_active_stack();
522   else
523     unselect_active_stack();
524 }
525
526 void Game::park_selected_stack()
527 {
528   Player *player = Playerlist::getActiveplayer();
529   Stack *stack = player->getActivestack();
530   assert(stack);
531   stack->setParked(true);
532
533   stack = player->getStacklist()->getNextMovable();
534   player->setActivestack(stack);
535
536   if (stack)
537     select_active_stack();
538   else
539     unselect_active_stack();
540 }
541
542 void Game::deselect_selected_stack()
543 {
544   Player *player = Playerlist::getActiveplayer();
545   player->setActivestack(0);
546   unselect_active_stack();
547 }
548
549 void Game::center_selected_stack()
550 {
551   Stack *stack = Playerlist::getActiveplayer()->getActivestack();
552   if (stack) 
553     select_active_stack();
554 }
555
556 void Game::search_stack(Stack *stack)
557 {
558   Player *player = Playerlist::getActiveplayer();
559   Ruin* ruin = GameMap::getRuin(stack);
560   Temple* temple = GameMap::getTemple(stack);
561
562   if (ruin && !ruin->isSearched() && stack->hasHero() &&
563       stack->getFirstHero()->getMoves() > 0 &&
564       ((ruin->isHidden() == true && ruin->getOwner() == player) ||
565        ruin->isHidden() == false))
566     {
567       Reward *reward;
568
569       reward = player->stackSearchRuin(stack, ruin);
570       if (ruin->hasSage() == true)
571         {
572           Sage *sage = ruin->generateSage();
573           if (player->isComputer() == false)
574             reward = sage_visited.emit(ruin, sage, stack);
575           else
576             reward = player->chooseReward(ruin, sage, stack);
577         }
578           
579       if (reward)
580         {
581           player->giveReward(stack, reward);
582           //FIXME: delete this reward, but don't delete the item, or map
583           redraw();
584           update_stack_info();
585           update_control_panel();
586           if (player->isComputer() == false)
587             ruin_searched.emit(ruin, stack, reward);
588         }
589       else
590         {
591           redraw();
592           update_stack_info();
593           update_control_panel();
594         }
595
596       update_sidebar_stats();
597     }
598   else if (temple && temple->searchable() && stack->getMoves() > 0)
599     {
600       int blessCount;
601       blessCount = player->stackVisitTemple(stack, temple);
602       bool wants_quest;
603       Hero *hero = stack->getFirstHeroWithoutAQuest();
604       if (player->isComputer() == false)
605         wants_quest = temple_searched.emit(hero, temple, blessCount);
606       else
607         wants_quest = player->chooseQuest(hero);
608       if (wants_quest && stack->hasHero())
609         {
610           Quest *q = player->heroGetQuest 
611             (hero, temple, 
612              GameScenario::s_razing_cities != GameParameters::NEVER);
613
614           if (q)
615             {
616               if (player->isComputer() == false)
617                 {
618                   Hero *hero;
619                   Army *a = stack->getArmyById(q->getHeroId());
620                   if (a)
621                     hero = dynamic_cast<Hero*>(a);
622                   quest_assigned.emit(hero, q);
623                 }
624             }
625         }
626     }
627 }
628
629 void Game::search_selected_stack()
630 {
631   Player *player = Playerlist::getActiveplayer();
632   Stack* stack = player->getActivestack();
633   return search_stack(stack);
634 }
635
636 void Game::stackUpdate(Stack* s)
637 {
638   if (!s)
639     s = Playerlist::getActiveplayer()->getActivestack();
640
641   //if player is not to be observed, bail now
642   if (s != NULL && s->getOwner()->isObservable() == false)
643       return;
644
645   if (s)
646     smallmap->center_view_on_tile(s->getPos(), true);
647
648   //redraw();
649
650   update_stack_info();
651   update_control_panel();
652
653 }
654
655 Army::Stat Game::heroGainsLevel(Hero * h)
656 {
657   // don't show a dialog if computer or enemy's armies advance
658   if (h->getOwner()->isComputer() == true ||
659       h->getOwner() != Playerlist::getInstance()->getActiveplayer())
660     return Playerlist::getInstance()->getActiveplayer()->chooseStat(h);
661
662   return hero_gains_level.emit(h);
663 }
664
665 void Game::newMedalArmy(Army* a, int medaltype)
666 {
667   // We don't want to have medal awards of computer players displayed
668   if (!a->getOwner()
669       || (a->getOwner()->getType() != Player::HUMAN)
670       || a->getOwner() != Playerlist::getInstance()->getActiveplayer())
671     return;
672
673   medal_awarded_to_army.emit(a, medaltype);
674   update_stack_info();
675 }
676
677 void Game::on_stack_grouped_or_ungrouped(Stack *s)
678 {
679   //this only happens when we double-click on a stack on the bigmap.
680   update_stack_info();
681   update_control_panel();
682 }
683
684 void Game::on_stack_selected(Stack* s)
685 {
686   update_stack_info();
687   update_control_panel();
688 }
689
690 void Game::on_city_queried (Vector<int> tile, City *c)
691 {
692   MapTipPosition mpos = bigmap->map_tip_position(tile);
693   city_tip_changed.emit(c, mpos);
694 }
695
696 void Game::on_city_unqueried ()
697 {
698   city_tip_changed.emit(NULL, MapTipPosition());
699 }
700
701 void Game::on_city_visited(City* c)
702 {
703   if (c)
704     {
705       city_visited.emit(c);
706       // some visible city properties (razed) may have changed
707       redraw();
708     }
709 }
710
711 void Game::on_ruin_queried (Ruin* r, bool brief)
712 {
713   if (r)
714     {
715       if (brief)
716         {
717           Glib::ustring str;
718
719           str = r->getName();
720           str += "\n";
721           if (r->isSearched())
722             // note to translators: whether a ruin has been searched
723             str += _("Explored");
724           else
725             // note to translators: whether a ruin has been searched
726             str += _("Unexplored");
727
728           MapTipPosition mpos = bigmap->map_tip_position(r->getArea());
729           map_tip_changed.emit(str, mpos);
730         }
731       else
732         {
733           ruin_visited.emit(r);
734         }
735     }
736   else
737     map_tip_changed.emit("", MapTipPosition());
738 }
739
740 void Game::on_signpost_queried (Signpost* s)
741 {
742   if (s)
743     {
744       Glib::ustring str;
745
746       str = s->getName();
747
748       MapTipPosition mpos = bigmap->map_tip_position(s->getArea());
749       map_tip_changed.emit(str, mpos);
750     }
751   else
752     map_tip_changed.emit("", MapTipPosition());
753 }
754
755 void Game::on_stack_unqueried ()
756 {
757   stack_tip_changed.emit(NULL, MapTipPosition());
758 }
759 void Game::on_stack_queried (Vector<int> tile)
760 {
761   MapTipPosition mpos = bigmap->map_tip_position(tile);
762   stack_tip_changed.emit(GameMap::getStacks(tile), mpos);
763 }
764
765 void Game::on_temple_queried (Temple* t, bool brief)
766 {
767   if (t)
768     {
769       if (brief)
770         {
771           Glib::ustring str;
772
773           str = t->getName();
774
775           MapTipPosition mpos = bigmap->map_tip_position(t->getArea());
776           map_tip_changed.emit(str, mpos);
777         }
778       else
779         {
780           temple_visited.emit(t);
781         }
782     }
783   else
784     map_tip_changed.emit("", MapTipPosition());
785 }
786
787 void Game::looting_city(City* city, int &gold)
788 {
789   Citylist *clist = Citylist::getInstance();
790   Playerlist *plist = Playerlist::getInstance();
791   Player *attacker = plist->getActiveplayer();
792   Player *defender = city->getOwner();
793   int amt = (defender->getGold() / (2 * clist->countCities (defender)) * 2);
794   // give (Enemy-Gold/(2Enemy-Cities)) to the attacker 
795   // and then take away twice that from the defender.
796   // the idea here is that some money is taken in the invasion
797   // and other monies are lost forever
798   defender->withdrawGold (amt);
799   amt /= 2;
800   attacker->addGold (amt);
801   gold = amt;
802   return;
803 }
804
805 void Game::invading_city(City* city, int gold)
806 {
807   Player *player = Playerlist::getInstance()->getActiveplayer();
808   
809   if (player->getType() == Player::HUMAN)
810     {
811       redraw();
812       CityDefeatedAction a = city_defeated.emit(city, gold);
813       gold = 0;
814
815       switch (a) {
816       case CITY_DEFEATED_OCCUPY:
817         player->cityOccupy(city);
818         break;
819
820       case CITY_DEFEATED_RAZE:
821         //the razing just happened in the are-you-sure dialog, and the user
822         //was sure.
823         city_razed.emit(city);
824         player->deteriorateDiplomaticRelationship (5);
825         break;
826
827       case CITY_DEFEATED_PILLAGE:
828           {
829             int pillaged_army_type = -1;
830             player->cityPillage(city, gold, &pillaged_army_type);
831             city_pillaged.emit(city, gold, pillaged_army_type);
832           }
833         break;
834
835       case CITY_DEFEATED_SACK:
836         std::list<guint32> sacked_types;
837         player->citySack(city, gold, &sacked_types);
838         city_sacked.emit(city, gold, sacked_types);
839         break;
840       }
841
842       if (!city->isBurnt())
843         city_visited.emit(city);
844     }
845
846   redraw();
847   update_stack_info();
848   update_sidebar_stats();
849   update_control_panel();
850 }
851
852 void Game::lock_inputs()
853 {
854   // don't accept modifying user input from now on
855   bigmap->reset_zoom();
856   bigmap->set_input_locked(true);
857   smallmap->set_input_locked(true);
858   input_locked = true;
859   update_control_panel();
860 }
861
862 void Game::unlock_inputs()
863 {
864   bigmap->set_input_locked(false);
865   smallmap->set_input_locked(false);
866   input_locked = false;
867   update_control_panel();
868 }
869
870 void Game::update_control_panel()
871 {
872   if (input_locked)
873     {
874       can_select_next_movable_stack.emit(false);
875       can_center_selected_stack.emit(false);
876       can_defend_selected_stack.emit(false);
877       can_park_selected_stack.emit(false);
878       can_deselect_selected_stack.emit(false);
879       can_search_selected_stack.emit(false);
880       can_plant_standard_selected_stack.emit(false);
881       can_move_selected_stack.emit(false);
882       can_move_selected_stack_along_path.emit(false);
883       can_move_all_stacks.emit(false);
884       can_group_ungroup_selected_stack.emit(false);
885       can_end_turn.emit(false);
886       can_disband_stack.emit(false);
887       can_change_signpost.emit(false);
888       can_see_history.emit(false);
889       can_see_diplomacy.emit(false);
890
891       return;
892     }
893
894   Player *player = Playerlist::getActiveplayer();
895   Stacklist* sl = player->getStacklist();
896
897   bool all_defending_or_parked = true;
898   for (Stacklist::iterator i = sl->begin(); i != sl->end(); ++i)
899     if (!(*i)->getDefending() && !(*i)->getParked() 
900         && *i != sl->getActivestack())
901       {
902         all_defending_or_parked = false;
903         break;
904       }
905
906   bool all_immobile = true;
907   for (Stacklist::iterator i = sl->begin(); i != sl->end(); ++i)
908     if (!(*i)->getDefending() && !(*i)->getParked() && (*i)->canMove()
909         && *i != sl->getActivestack())
910       {
911         all_immobile = false;
912         break;
913       }
914   can_select_next_movable_stack.emit(!all_defending_or_parked && !all_immobile);
915
916   // if any stack can move, enable the moveall button
917   can_move_all_stacks.emit(sl->enoughMoves());
918
919   Stack *stack = player->getActivestack();
920
921   can_defend_selected_stack.emit(stack != 0);
922   can_park_selected_stack.emit(stack != 0);
923   can_deselect_selected_stack.emit(stack != 0);
924   can_center_selected_stack.emit(stack != 0);
925
926   if (stack)
927     {
928       can_move_selected_stack_along_path.emit
929         ((!stack->getPath()->empty() && stack->enoughMoves()) ||
930          (!stack->getPath()->empty() && stack->getPath()->getMovesExhaustedAtPoint() > 0));
931
932       /*
933        * a note about searching.
934        * ruins can be searched by stacks that have a hero, and when the
935        * hero has moves left.  also the ruin must be unexplored.
936        * temples can be searched by any stack, when the stack has 
937        * movement left.
938        */
939       if (stack->getMoves() > 0)
940         {
941           Temple *temple;
942           temple = GameMap::getTemple(stack);
943           can_search_selected_stack.emit(temple);
944           can_move_selected_stack.emit(true);
945         }
946
947       if (stack->hasHero())
948         {
949           Ruin *ruin = GameMap::getRuin(stack);
950           if (stack->getFirstHero()->getMoves() > 0 && ruin)
951             can_search_selected_stack.emit(!ruin->isSearched());
952
953           //does the hero have the player's standard?
954           for (Stack::iterator it = stack->begin(); it != stack->end(); it++)
955             {
956               if ((*it)->isHero())
957                 {
958                   Hero *hero = dynamic_cast<Hero*>((*it));
959                   if (hero->getBackpack()->getPlantableItem(player))
960                     {
961                           //can't plant on city/ruin/temple/signpost
962                           City *city = GameMap::getCity(stack->getPos());
963                           Temple *temple = GameMap::getTemple(stack);
964                           Ruin *ruin = GameMap::getRuin(stack);
965                           Signpost *sign = GameMap::getSignpost(stack);
966                           if (!city && !temple && !ruin && !sign)
967                             {
968                               GameMap *gm = GameMap::getInstance();
969                               MapBackpack *backpack;
970                               Vector<int> pos = stack->getPos();
971                               backpack = gm->getTile(pos)->getBackpack();
972                               bool standard_already_planted = 
973                                 backpack->getFirstPlantedItem() != NULL;
974                               //are there any other standards here?
975                               if (standard_already_planted == false)
976                                 can_plant_standard_selected_stack.emit(true);
977                             }
978                     }
979                 }
980             }
981         }
982       else
983         {
984           can_plant_standard_selected_stack.emit(false);
985         }
986
987       if (GameMap::getSignpost(stack))
988         can_change_signpost.emit(true);
989
990       can_disband_stack.emit(true);
991       can_group_ungroup_selected_stack.emit(true);
992     }
993   else
994     {
995       can_search_selected_stack.emit(false);
996       can_move_selected_stack.emit(false);
997       can_move_selected_stack_along_path.emit(false);
998       can_disband_stack.emit(false);
999       can_group_ungroup_selected_stack.emit(false);
1000       can_plant_standard_selected_stack.emit(false);
1001     }
1002
1003   if (d_gameScenario->getRound() > 1)
1004     can_see_history.emit(true);
1005   else
1006     can_see_history.emit(false);
1007     
1008   can_see_diplomacy.emit(GameScenarioOptions::s_diplomacy);
1009
1010   can_end_turn.emit(true);
1011 }
1012
1013 GameBigMap &Game::get_bigmap()
1014 {
1015   assert(bigmap.get());
1016   return *bigmap.get();
1017 }
1018
1019 SmallMap &Game::get_smallmap()
1020 {
1021   assert(smallmap.get());
1022   return *smallmap.get();
1023 }
1024
1025 void Game::startGame()
1026 {
1027   debug ("start_game()");
1028       
1029   center_view_on_city();
1030   update_sidebar_stats();
1031   update_control_panel();
1032   update_stack_info();
1033   lock_inputs();
1034
1035   d_nextTurn->start();
1036   if (Playerlist::getInstance()->countPlayersAlive())
1037     update_control_panel();
1038 }
1039
1040 void Game::loadGame()
1041 {
1042   //if pbm and human
1043   //if pbm and not human, then bail
1044
1045   Player *player = Playerlist::getActiveplayer();
1046   if (!player)
1047     {
1048       Playerlist::getInstance()->nextPlayer();
1049       player = Playerlist::getActiveplayer();
1050     }
1051
1052   if (player->getType() == Player::HUMAN && (d_gameScenario->getPlayMode() == GameScenario::HOTSEAT))
1053     {
1054       //human players want access to the controls and an info box
1055       unlock_inputs();
1056       player->setActivestack(0);
1057       center_view_on_city();
1058       update_sidebar_stats();
1059       update_control_panel();
1060       update_stack_info();
1061       game_loaded.emit(player);
1062       if (player->getType() == Player::HUMAN)
1063         d_nextTurn->setContinuingTurn();
1064     }
1065   else if (player->getType() == Player::HUMAN && 
1066            d_gameScenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
1067     {
1068       if (player->hasAlreadyInitializedTurn())
1069         {
1070           unlock_inputs();
1071           player->setActivestack(0);
1072           center_view_on_city();
1073           update_sidebar_stats();
1074           update_control_panel();
1075           update_stack_info();
1076           game_loaded.emit(player);
1077           player->loadPbmGame();
1078           d_nextTurn->setContinuingTurn();
1079         }
1080       else
1081         {
1082           lock_inputs();
1083         }
1084     }
1085   else
1086     lock_inputs();
1087
1088   d_nextTurn->start();
1089 #if 0
1090   else
1091     {
1092       lock_inputs();
1093       update_sidebar_stats();
1094       player->startTurn();
1095       d_nextTurn->endTurn();
1096       if (Playerlist::getInstance()->countPlayersAlive())
1097         update_control_panel();
1098     }
1099 #endif
1100 }
1101
1102 void Game::stopGame()
1103 {
1104   d_nextTurn->stop();
1105 }
1106
1107 bool Game::saveGame(std::string file)
1108 {
1109   return d_gameScenario->saveGame(file);
1110 }
1111
1112 void Game::blank(bool on)
1113 {
1114   if (GameScenarioOptions::s_hidden_map == true)
1115     {
1116       bigmap->blank(on);
1117       smallmap->blank(on);
1118     }
1119 }
1120
1121 void Game::init_turn_for_player(Player* p)
1122 {
1123   Playerlist* pl = Playerlist::getInstance();
1124
1125   blank(true);
1126
1127   next_player_turn.emit(p, d_gameScenario->getRound());
1128
1129   blank(false);
1130
1131   if (p->isObservable() == true)
1132     center_view_on_city();
1133
1134   if (p->getType() == Player::HUMAN)
1135     {
1136       if (Commentator::getInstance()->hasComment() == true)
1137         {
1138           std::vector<std::string> comments =
1139             Commentator::getInstance()->getComments(p);
1140           if (comments.size() > 0)
1141             commentator_comments.emit(comments[rand() % comments.size()]);
1142         }
1143     }
1144
1145   p->maybeRecruitHero();
1146
1147   if (p->getType() == Player::HUMAN)
1148     {
1149       unlock_inputs();
1150
1151       update_sidebar_stats();
1152       update_stack_info();
1153       update_control_panel();
1154       redraw();
1155
1156       // update the diplomacy icon if we've received a proposal
1157       bool proposal_received = false;
1158       for (Playerlist::iterator it = pl->begin(); it != pl->end(); ++it)
1159         {
1160           if ((*it) == pl->getNeutral())
1161             continue;
1162           if ((*it) == p)
1163             continue;
1164           if((*it)->isDead())
1165             continue;
1166           if ((*it)->getDiplomaticProposal(p) != Player::NO_PROPOSAL)
1167             {
1168               proposal_received = true;
1169               break;
1170             }
1171         }
1172       received_diplomatic_proposal.emit(proposal_received);
1173       //check to see if we've turned off production due to destitution.
1174       bool destitute = false;
1175       if (p->countDestituteCitiesThisTurn() > 0)
1176         destitute = true;
1177       city_too_poor_to_produce.emit(destitute);
1178     }
1179   else
1180     {
1181       //SDL_Delay(250);
1182     }
1183 }
1184
1185 void Game::on_player_died(Player *player)
1186 {
1187   const Playerlist* pl = Playerlist::getInstance();
1188   if (pl->getNoOfPlayers() <= 1)
1189     game_over.emit(pl->getFirstLiving());
1190   else
1191     player_died.emit(player);
1192 }
1193
1194       
1195 void Game::on_fight_started(Fight &fight)
1196 {
1197   
1198   //don't show the battle if the ai is attacking neutral
1199   bool ai_attacking_neutral = false;
1200   if (fight.getDefenders().front()->getOwner() == Playerlist::getInstance()->getNeutral() && Playerlist::getActiveplayer()->getType() != Player::HUMAN)
1201     ai_attacking_neutral = true;
1202
1203   //show the battle if we're attacking an observable player
1204   bool attacking_observable_player = false;
1205   if (fight.getDefenders().front()->getOwner()->isObservable())
1206     attacking_observable_player = true;
1207
1208   //don't show the battle if we're ai and we're on a hidden map
1209   bool ai_attacking_on_hidden_map = false;
1210   if (fight.getAttackers().front()->getOwner()->getType() != Player::HUMAN &&
1211       GameScenario::s_hidden_map == true)
1212     ai_attacking_on_hidden_map = true;
1213
1214   if ((Playerlist::getActiveplayer()->isObservable() == true ||
1215       attacking_observable_player) && !ai_attacking_neutral &&
1216       !ai_attacking_on_hidden_map)
1217     {
1218       Vector<int> pos = fight.getAttackers().front()->getPos();
1219       if (GameScenario::s_hidden_map == false)
1220         smallmap->center_view_on_tile(pos, true);
1221       fight_started.emit(Fight::calculateFightBox(fight), fight);
1222     }
1223   else if ((Playerlist::getActiveplayer()->isObservable() == true ||
1224       attacking_observable_player) && ai_attacking_neutral &&
1225       !ai_attacking_on_hidden_map)
1226     {
1227       Vector<int> pos = fight.getAttackers().front()->getPos();
1228       if (GameScenario::s_hidden_map == false)
1229         smallmap->center_view_on_tile(pos, true);
1230       abbreviated_fight_started.emit(Fight::calculateFightBox(fight));
1231     }
1232 }
1233
1234 void Game::center_view_on_city()
1235 {
1236   const Player* p = Playerlist::getInstance()->getActiveplayer();
1237
1238   if (p == Playerlist::getInstance()->getNeutral())
1239     return;
1240   if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1241       GameScenario::s_hidden_map == true)
1242     return;
1243   //FIXME: if player is not to be observed, bail now
1244   // preferred city is a capital city that belongs to the player 
1245   for (Citylist::iterator i = Citylist::getInstance()->begin();
1246        i != Citylist::getInstance()->end(); i++)
1247     {
1248       City *c = *i;
1249       if (c->getOwner() == p && c->isCapital() &&
1250           c->getCapitalOwner() == p)
1251         {
1252           smallmap->center_view_on_tile(c->getPos(), 
1253                                         !GameScenario::s_hidden_map);
1254           return;
1255         }
1256     }
1257
1258   // okay, then find any city that belongs to the player and center on it
1259   for (Citylist::iterator i = Citylist::getInstance()->begin();
1260        i != Citylist::getInstance()->end(); i++)
1261     {
1262       City *c = *i;
1263       if (c->getOwner() == p)
1264         {
1265           smallmap->center_view_on_tile(c->getPos(), 
1266                                         !GameScenario::s_hidden_map);
1267           break;
1268         }
1269     }
1270 }
1271 void Game::select_active_stack()
1272 {
1273   //if (Playerlist::getActiveplayer()->getType() != Player::HUMAN &&
1274       //GameScenario::s_hidden_map == true)
1275     //return;
1276   Player *p = Playerlist::getInstance()->getActiveplayer();
1277   smallmap->center_view_on_tile (p->getActivestack()->getPos(), true);
1278   bigmap->select_active_stack();
1279 }
1280 void Game::unselect_active_stack()
1281 {
1282   bigmap->unselect_active_stack();
1283 }
1284
1285 bool Game::maybeTreachery(Stack *stack, Player *them, Vector<int> pos)
1286 {
1287   Player *me = stack->getOwner();
1288   bool treachery = false;
1289   if (me->isComputer())
1290     {
1291       if (me->getType() == Player::AI_FAST)
1292         {
1293           AI_Fast *ai = dynamic_cast<AI_Fast*>(me);
1294           treachery = ai->chooseTreachery (stack, them, pos);
1295         }
1296       else if (me->getType() == Player::AI_SMART)
1297         {
1298           AI_Smart *ai = dynamic_cast<AI_Smart*>(me);
1299           treachery = ai->chooseTreachery (stack, them, pos);
1300         }
1301     }
1302   if (treachery == false)
1303     return false;
1304   me->proposeDiplomacy (Player::NO_PROPOSAL, them);
1305   me->declareDiplomacy (Player::AT_WAR, them);
1306   them->proposeDiplomacy (Player::NO_PROPOSAL, me);
1307   them->declareDiplomacy (Player::AT_WAR, me);
1308   History_DiplomacyTreachery *item = new History_DiplomacyTreachery();
1309   item->fillData(them);
1310   me->addHistory(item);
1311
1312   me->deteriorateDiplomaticRelationship (5);
1313   them->improveDiplomaticRelationship (2, me);
1314
1315   return true;
1316 }
1317
1318 void Game::nextRound()
1319 {
1320   Playerlist::getInstance()->nextRound
1321     (GameScenarioOptions::s_diplomacy, 
1322      &GameScenarioOptions::s_surrender_already_offered);
1323 }
1324     
1325 void Game::on_surrender_offered(Player *recipient)
1326 {
1327   Playerlist *plist = Playerlist::getInstance();
1328   if (enemy_offers_surrender.emit(plist->countPlayersAlive() - 1))
1329     {
1330       plist->surrender();
1331       surrender_answered.emit(true);
1332       game_over.emit(recipient);
1333     }
1334   else
1335     surrender_answered.emit(false);
1336 }
1337
1338 void Game::recalculate_moves_for_stack(Stack *s)
1339 {
1340   if (!s)
1341     s = Playerlist::getActiveplayer()->getActivestack();
1342   if (s)
1343     {
1344       s->getPath()->recalculate(s);
1345       redraw();
1346       update_control_panel();
1347     }
1348 }
1349     
1350 void Game::on_city_fight_finished(City *city, Fight::Result result)
1351 {
1352   if (result != Fight::ATTACKER_WON)
1353     {
1354       // we didn't suceed in defeating the defenders
1355       //if this is a neutral city, and we're playing with 
1356       //active neutral cities, AND it hasn't already been attacked
1357       //then it's production gets turned on
1358       Player *neu = city->getOwner(); //neutral player
1359       if (GameScenario::s_neutral_cities == GameParameters::ACTIVE &&
1360           neu == Playerlist::getInstance()->getNeutral() &&
1361           city->getActiveProductionSlot() == -1)
1362         {
1363           //great, then let's turn on the production.
1364           //well, we already made a unit, and we want to produce more
1365           //of it.
1366           Stack *o = GameMap::getStacks(city->getPos())->getFriendlyStack(neu);
1367           if (o)
1368             {
1369               int army_type = o->getStrongestArmy()->getTypeId();
1370               for (guint32 i = 0; i < city->getMaxNoOfProductionBases(); i++)
1371                 {
1372                   if (city->getArmytype(i) == army_type)
1373                     {
1374                       // hey, we found the droid we were looking for
1375                       city->setActiveProductionSlot(i);
1376                       break;
1377                     }
1378                 }
1379             }
1380         }
1381     }
1382   return;
1383 }
1384     
1385 bool Game::recruitHero(HeroProto *hero, City *city, int gold)
1386 {
1387   bool retval; 
1388   if (city->getOwner()->isComputer())
1389     retval = city->getOwner()->chooseHero (hero, city, gold);
1390   else
1391     {
1392       retval = hero_offers_service.emit (city->getOwner(), hero, city, gold);
1393       if (d_gameScenario->getRound() == 1)
1394         city_visited.emit(city);
1395     }
1396   return retval;
1397 }
1398     
1399 bool Game::saveTurnFile(std::string turnfile)
1400 {
1401   bool broken;
1402   //trigger the GameServer to spit out a set of networkactions and networkhistory events for the active player, into a file.
1403   if (d_gameScenario->getPlayMode() == GameScenario::PLAY_BY_MAIL)
1404     PbmGameServer::getInstance()->endTurn(turnfile, broken);
1405   return true;
1406 }
1407
1408 void Game::inhibitAutosaveRemoval(bool inhibit)
1409 {
1410   if (d_gameScenario)
1411     d_gameScenario->inhibitAutosaveRemoval(inhibit);
1412 }
1413
1414 void Game::endOfGameRoaming(Player *winner)
1415 {
1416   Playerlist* pl = Playerlist::getInstance();
1417   pl->setWinningPlayer(winner);
1418
1419   winner->immobilize();
1420   d_gameScenario->s_see_opponents_stacks = true;
1421   d_gameScenario->s_see_opponents_production = true;
1422   bigmap->d_see_opponents_stacks = true;
1423   bigmap->d_see_opponents_production = true;
1424   center_view_on_city();
1425
1426   unlock_inputs();
1427
1428   update_sidebar_stats();
1429   update_stack_info();
1430   update_control_panel();
1431   redraw();
1432 }
1433
1434 void Game::stack_arrives_on_tile(Stack *stack, Vector<int> tile)
1435 {
1436   StackTile *stile = GameMap::getInstance()->getTile(tile)->getStacks();
1437   stile->arriving(stack);
1438 }
1439
1440 void Game::stack_leaves_tile(Stack *stack, Vector<int> tile)
1441 {
1442   StackTile *stile = GameMap::getInstance()->getTile(tile)->getStacks();
1443   bool left = stile->leaving(stack);
1444   if (left == false)
1445     {
1446       if (stack == NULL)
1447         {
1448           printf("stack is %p\n", stack);
1449           printf("WTFFF!!!!!!!!!!!!!!!!!!!!\n");
1450           return;
1451         }
1452     }
1453 }
1454     
1455 void Game::stack_searches_ruin(Ruin *ruin, Stack *stack)
1456 {
1457   search_stack(stack);
1458 }
1459     
1460 void Game::stack_searches_temple(Temple *temple, Stack *stack)
1461 {
1462   search_stack(stack);
1463 }