initial commit, lordsawar source, slightly modified
[lordsawar] / src / NextTurnHotseat.cpp
1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2007, 2008, 2009 Ben Asselstine
3 // Copyright (C) 2007, 2008 Ole Laursen
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Library General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
18 //  02110-1301, USA.
19
20 #include "NextTurnHotseat.h"
21
22 #include "playerlist.h"
23 #include "citylist.h"
24 #include "ruinlist.h"
25 #include "stacklist.h"
26 #include "armysetlist.h"
27 #include "hero.h"
28 #include "vectoredunitlist.h"
29 #include "FogMap.h"
30 #include "history.h"
31 #include "QuestsManager.h"
32 #include "ai_fast.h" //remove me
33
34 #include "path.h"
35
36 using namespace std;
37 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl;}
38 //#define debug(x)
39
40 NextTurnHotseat::NextTurnHotseat(bool turnmode, bool random_turns)
41     :NextTurn(turnmode, random_turns)
42 {
43   continuing_turn = false;
44   
45   Playerlist* plist = Playerlist::getInstance();
46   for (Playerlist::iterator i = plist->begin(); i != plist->end(); ++i) {
47     Player *p = *i;
48     p->ending_turn.connect(sigc::mem_fun(this, &NextTurn::endTurn));
49   }
50 }
51
52 NextTurnHotseat::~NextTurnHotseat()
53 {
54 }
55
56 void NextTurnHotseat::start()
57 {
58     //We need the playerlist a lot, so maintain a copy of it.
59
60     //set first player as active if no active player exists
61     if (!Playerlist::getActiveplayer())
62       nextPlayer();
63         
64     while (!d_stop)
65     {
66       supdating.emit();
67
68         // do various start-up tasks
69         if (continuing_turn)
70           {
71             continuing_turn = false;
72             return;
73           }
74
75         startTurn();
76        
77         // inform everyone about the next turn 
78         snextTurn.emit(Playerlist::getActiveplayer());
79     
80         splayerStart.emit(Playerlist::getActiveplayer());
81
82         // let the player do his or her duties...
83         bool continue_loop = Playerlist::getActiveplayer()->startTurn();
84         if (!continue_loop || d_stop)
85           return;
86         
87         //Now do some cleanup at the end of the turn.
88         finishTurn();
89
90         //...and initiate the next one.
91         nextPlayer();
92         
93         //if it is the first player's turn now, a new round has started
94         if (Playerlist::getInstance()->getActiveplayer() == 
95             Playerlist::getInstance()->getFirstLiving())
96         
97           {
98             if (Playerlist::getInstance()->checkPlayers() == true)
99               {
100                 if (Playerlist::getInstance()->getNoOfPlayers() <= 1)
101                   break;
102                 if (Playerlist::getActiveplayer()->isDead())
103                   nextPlayer();
104               }
105             finishRound();
106             snextRound.emit();
107           }
108     }
109 }
110
111 void NextTurnHotseat::endTurn()
112 {
113   // Finish off the player and transfers the control to the start function
114   // again.
115   finishTurn();
116   if (Playerlist::getInstance()->checkPlayers() == true)
117     {
118       if (d_stop)
119         return;
120       if (Playerlist::getInstance()->getNoOfPlayers() <= 1)
121         return;
122     }
123   nextPlayer();
124
125   //this is problematic when the first player dies.
126   //end the turn if all living players have ended their turn.
127   if (Playerlist::getInstance()->isEndOfRound() == true)
128     {
129       finishRound();
130       snextRound.emit();
131     }
132
133   start();
134 }
135
136 void NextTurnHotseat::startTurn()
137 {
138   //this function is called before a player starts his turn. Some
139   //items you could imagine to be placed here: healing/building
140   //units, check for joining heroes...
141
142   //a shortcut
143   Player* p = Playerlist::getActiveplayer();
144
145   p->initTurn();
146
147   //calculate upkeep and income
148   p->calculateUpkeep();
149   p->calculateIncome();
150
151   //if turnmode is set, create/heal armies at player's turn
152   if (d_turnmode)
153     {
154
155       //if (p->getType() != Player::NETWORKED)
156       
157       //collect taxes
158       Citylist::getInstance()->collectTaxes(p);
159
160       guint32 num_cities = Citylist::getInstance()->countCities(p);
161       p->getStacklist()->collectTaxes(p, num_cities);
162
163       //vector armies (needs to preceed city's next turn)
164       VectoredUnitlist::getInstance()->nextTurn(p);
165
166       //pay upkeep for existing stacks
167       p->getStacklist()->payUpkeep(p);
168
169       //reset moves, and heal stacks
170       p->getStacklist()->nextTurn();
171
172       //build new armies
173       Citylist::getInstance()->nextTurn(p);
174
175     }
176   p->calculateUpkeep();
177
178   QuestsManager::getInstance()->nextTurn(p);
179 }
180
181 void NextTurnHotseat::finishTurn()
182 {
183   //Put everything that has to be done before the next player starts
184   //his turn here. E.g. one could clear some caches.
185   Player *p = Playerlist::getActiveplayer();
186   p->getFogMap()->smooth();
187   p->endTurn();
188 }
189
190 void NextTurnHotseat::finishRound()
191 {
192   Playerlist *plist = Playerlist::getInstance();
193   //Put everything that has to be done when a new round starts in here.
194   //E.g. increase the round number in GameScenario. (this is done with
195   //the snextRound signal, but useful for an example).
196
197   if (!d_turnmode)
198     {
199       //do this for all players at once
200       
201       for (Playerlist::iterator it = plist->begin(); it != plist->end(); it++)
202         {
203           if ((*it)->isDead())
204             continue;
205
206           //collect monies from cities
207           Citylist::getInstance()->collectTaxes(*it);
208
209           guint32 num_cities = Citylist::getInstance()->countCities(*it);
210           (*it)->getStacklist()->collectTaxes((*it), num_cities);
211
212           //vector armies (needs to preceed city's next turn)
213           VectoredUnitlist::getInstance()->nextTurn(*it);
214
215           //pay for existing armies
216           (*it)->getStacklist()->payUpkeep(*it);
217
218           //reset, and heal armies
219           (*it)->getStacklist()->nextTurn();
220
221           //produce new armies
222           Citylist::getInstance()->nextTurn(*it);
223
224         }
225     }
226
227   // heal the stacks in the ruins
228   Ruinlist* rl = Ruinlist::getInstance();
229   for (Ruinlist::iterator it = rl->begin(); it != rl->end(); it++)
230     {
231       Stack* keeper = (*it)->getOccupant();
232       if (keeper)
233         keeper->nextTurn();
234     }
235     
236   if (d_random_turns)
237     {
238       plist->randomizeOrder();
239       nextPlayer();
240     }
241
242 }