initial commit, lordsawar source, slightly modified
[lordsawar] / src / NextTurnPbm.cpp
1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2007, 2008 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 "NextTurnPbm.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 NextTurnPbm::NextTurnPbm(bool turnmode, bool random_turns)
41         :NextTurn(turnmode, random_turns)
42 {
43   Playerlist* plist = Playerlist::getInstance();
44   for (Playerlist::iterator i = plist->begin(); i != plist->end(); ++i) {
45     Player *p = *i;
46     p->ending_turn.connect(sigc::mem_fun(this, &NextTurn::endTurn));
47   }
48 }
49
50 NextTurnPbm::~NextTurnPbm()
51 {
52 }
53
54 void NextTurnPbm::start()
55 {
56     //We need the playerlist a lot, so maintain a copy of it.
57     Playerlist* plist = Playerlist::getInstance();
58
59     //set first player as active if no active player exists
60     if (!plist->getActiveplayer())
61         nextPlayer();
62
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(plist->getActiveplayer());
79     
80         if (plist->getNoOfPlayers() <= 2)
81           {
82             if (plist->checkPlayers()) //end of game detected
83               return;
84           }
85
86         splayerStart.emit(plist->getActiveplayer());
87
88         // let the player do his or her duties...
89         bool continue_loop = plist->getActiveplayer()->startTurn();
90         if (!continue_loop)
91           return;
92         
93         //Now do some cleanup at the end of the turn.
94         finishTurn();
95
96         //...and initiate the next one.
97         nextPlayer();
98         
99         //if it is the first player's turn now, a new round has started
100         if (Playerlist::getInstance()->getActiveplayer() == 
101             Playerlist::getInstance()->getFirstLiving())
102         
103           {
104             if (plist->checkPlayers() == true)
105               {
106                 if (plist->getNoOfPlayers() <= 1)
107                   break;
108                 if (plist->getActiveplayer()->isDead())
109                   nextPlayer();
110               }
111             finishRound();
112             snextRound.emit();
113           }
114
115         break;
116     }
117 }
118
119 void NextTurnPbm::endTurn()
120 {
121   // Finish off the player and transfers the control to the start function
122   // again.
123   finishTurn();
124   nextPlayer();
125
126   if (Playerlist::getActiveplayer() == Playerlist::getInstance()->getFirstLiving())
127     {
128       finishRound();
129       snextRound.emit();
130     }
131 }
132
133 void NextTurnPbm::startTurn()
134 {
135   //this function is called before a player starts his turn. Some
136   //items you could imagine to be placed here: healing/building
137   //units, check for joining heroes...
138
139   //a shortcut
140   Player* p = Playerlist::getActiveplayer();
141
142   p->initTurn();
143
144   //calculate upkeep and income
145   p->calculateUpkeep();
146   p->calculateIncome();
147
148   //if turnmode is set, create/heal armies at player's turn
149   if (d_turnmode)
150     {
151
152       //if (p->getType() != Player::NETWORKED)
153       
154       //collect taxes
155       Citylist::getInstance()->collectTaxes(p);
156
157       guint32 num_cities = Citylist::getInstance()->countCities(p);
158       p->getStacklist()->collectTaxes(p, num_cities);
159
160       //vector armies (needs to preceed city's next turn)
161       VectoredUnitlist::getInstance()->nextTurn(p);
162
163       //pay upkeep for existing stacks
164       p->getStacklist()->payUpkeep(p);
165
166       //reset moves, and heal stacks
167       p->getStacklist()->nextTurn();
168
169       //build new armies
170       Citylist::getInstance()->nextTurn(p);
171
172     }
173   p->calculateUpkeep();
174
175   QuestsManager::getInstance()->nextTurn(p);
176 }
177
178 void NextTurnPbm::finishTurn()
179 {
180   //Put everything that has to be done before the next player starts
181   //his turn here. E.g. one could clear some caches.
182   Player *p = Playerlist::getActiveplayer();
183   p->getFogMap()->smooth();
184   p->endTurn();
185 }
186
187 void NextTurnPbm::finishRound()
188 {
189   Playerlist *plist = Playerlist::getInstance();
190   //Put everything that has to be done when a new round starts in here.
191   //E.g. increase the round number in GameScenario. (this is done with
192   //the snextRound signal, but useful for an example).
193
194   if (!d_turnmode)
195     {
196       //do this for all players at once
197       
198       for (Playerlist::iterator it = plist->begin(); it != plist->end(); it++)
199         {
200           if ((*it)->isDead())
201             continue;
202
203           //collect monies from cities
204           Citylist::getInstance()->collectTaxes(*it);
205
206           guint32 num_cities = Citylist::getInstance()->countCities(*it);
207           (*it)->getStacklist()->collectTaxes((*it), num_cities);
208
209           //vector armies (needs to preceed city's next turn)
210           VectoredUnitlist::getInstance()->nextTurn(*it);
211
212           //pay for existing armies
213           (*it)->getStacklist()->payUpkeep(*it);
214
215           //reset, and heal armies
216           (*it)->getStacklist()->nextTurn();
217
218           //produce new armies
219           Citylist::getInstance()->nextTurn(*it);
220
221         }
222     }
223
224   // heal the stacks in the ruins
225   Ruinlist* rl = Ruinlist::getInstance();
226   for (Ruinlist::iterator it = rl->begin(); it != rl->end(); it++)
227     {
228       Stack* keeper = (*it)->getOccupant();
229       if (keeper)
230         keeper->nextTurn();
231     }
232     
233   if (d_random_turns)
234     {
235       plist->randomizeOrder();
236       nextPlayer();
237     }
238
239 }