]> ruin.nu Git - hbs.git/blob - bs/fleet.cpp
added code so you lose ships if you steal..
[hbs.git] / bs / fleet.cpp
1 /***************************************************************************
2                           fleet.cpp  -  description
3                              -------------------
4     begin                : Tue Jan 22 2002
5     copyright            : (C) 2002 by Michael Andreen
6     email                : whale@linux.nu
7  ***************************************************************************/
8
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include "fleet.h"
19
20 #include <iostream>
21 #include <cstdlib>
22 using namespace std;
23
24 //Static variables
25 map<string, vector<int> > Fleet::s_Races;
26 UnitList Fleet::s_Units;
27
28 Fleet::Fleet()
29 {
30         m_iETA = 0;
31         m_iStays = 3;
32         m_sRace = "Cathaar";
33 }
34
35 Fleet::~Fleet(){
36 }
37
38 //////////////////////////////////////////////////////////////////////////
39 //
40 void Fleet::setName(string sName)
41 {
42         m_sName = sName;
43 }
44
45 //////////////////////////////////////////////////////////////////////////
46 //
47 string Fleet::name() const
48 {
49         return m_sName;
50 }
51
52 //////////////////////////////////////////////////////////////////////////
53 //
54 /** This function first sets the race, then it iterates through the the 
55  * s_Races and checks if it finds the race it returns true, if it reaches
56  * the end without finding it it returns false.
57  */
58 bool Fleet::setRace(string sRace)
59 {
60         m_sRace = sRace;
61         for (map<string, vector<int> >::iterator i = s_Races.begin(); i != s_Races.end(); i++)
62         {
63                 if (m_sRace == (*i).first)
64                         return true;
65         }
66         return false;
67 }
68
69 //////////////////////////////////////////////////////////////////////////
70 //
71 string Fleet::race() const
72 {
73         return m_sRace;
74 }
75
76 //////////////////////////////////////////////////////////////////////////
77 //
78 /** This function iterates through m_Fleet and adds all numbers together to
79  * produce a total.
80  */
81 int Fleet::numberOfShips() const
82 {
83         int total = 0;
84
85         for (map<string, vector<int> >::const_iterator i = m_Fleet.begin(); i != m_Fleet.end(); ++i)
86         {
87                 if (i->second.size() != 0)
88                         total += i->second[0];
89         }
90
91         return total;
92 }
93
94 //////////////////////////////////////////////////////////////////////////
95 //
96 void Fleet::setETA(int eta)
97 {
98         m_iETA = eta;
99 }
100
101 //////////////////////////////////////////////////////////////////////////
102 //
103 int  Fleet::ETA() const
104 {
105         return m_iETA;
106 }
107
108 //////////////////////////////////////////////////////////////////////////
109 //
110 void Fleet::setRaces(map<string, vector<int> >& races)
111 {
112         s_Races = races;
113 }
114
115 //////////////////////////////////////////////////////////////////////////
116 //
117 void Fleet::setUnits(UnitList& units)
118 {
119         s_Units = units;
120
121         
122 /*
123         for (UnitList::iterator i = s_Units.begin(); i != s_Units.end(); i++)
124         {
125                 cerr << s_Units[(*i).first].Name() << "\t\t"
126                         << s_Units[(*i).first].race() <<"\t"
127                         << s_Units[(*i).first].unitClass() << "\t"
128                         << s_Units[(*i).first].target(0) << "\t"
129                         << s_Units[(*i).first].target(1) << "\t"
130                         << s_Units[(*i).first].target(2) << "\t"
131                         << s_Units[(*i).first].initiative() << "\t"
132                         << s_Units[(*i).first].agility() << "\t"
133                         << s_Units[(*i).first].weaponSpeed() << "\t"
134                         << s_Units[(*i).first].guns() << "\t"
135                         << s_Units[(*i).first].power() << "\t"
136                         << s_Units[(*i).first].armor() << "\t"
137                         << s_Units[(*i).first].EMP() << "\t"
138                         << s_Units[(*i).first].totRes() << "\t"
139                         << s_Units[(*i).first].fuel() << "\t"
140                         << s_Units[(*i).first].ETA() << "\t"
141                         << s_Units[(*i).first].type() << endl;
142         }
143 */      
144 }
145
146 //////////////////////////////////////////////////////////////////////////
147 //
148 const map<string, vector<int> >& Fleet::Races()
149 {
150         return s_Races;
151 }
152
153 //////////////////////////////////////////////////////////////////////////
154 //
155 const UnitList& Fleet::Units()
156 {
157         return s_Units;
158 }
159
160 //////////////////////////////////////////////////////////////////////////
161 //
162 vector<int> Fleet::RacesAllowed() const
163 {
164         return s_Races[m_sRace];
165 }
166
167 //////////////////////////////////////////////////////////////////////////
168 //
169 unsigned Fleet::score(int tick = 0) const
170 {
171         unsigned tot_score = 0;
172
173         for (FleetList::const_iterator i = m_Fleet.begin(); i != m_Fleet.end(); ++i)
174         {
175                 int ticks =     i->second.size();
176                 if (ticks == 0)
177                         continue;
178                 --ticks;
179                 if ( ticks < tick)
180                         tot_score += i->second[ticks] * s_Units[i->first].totRes() / 10;
181                 else
182                         tot_score += i->second[tick] * s_Units[i->first].totRes() / 10;
183         }
184
185         return tot_score;
186 }
187
188 //////////////////////////////////////////////////////////////////////////
189 //
190 void Fleet::setFleet(string unittype, int number, int tick = 0)
191 {
192         int earlier = 0;
193         int ticks = m_Fleet[unittype].size();
194
195         if (ticks != 0)
196                 earlier = m_Fleet[unittype][ticks - 1];
197
198         for (int i = ticks; i <= tick; ++i)
199         {
200                 m_Fleet[unittype].push_back(earlier);
201         }
202         m_Fleet[unittype][tick] = number;
203 }
204
205 //////////////////////////////////////////////////////////////////////////
206 //
207 void Fleet::addFleet(std::string unittype, int number, int tick = 0)
208 {
209         int earlier = 0;
210         int ticks = m_Fleet[unittype].size();
211
212         if (ticks != 0)
213                 earlier = m_Fleet[unittype][ticks - 1];
214
215         for (int i = ticks; i <= tick; ++i)
216         {
217                 m_Fleet[unittype].push_back(earlier);
218         }
219         m_Fleet[unittype][tick] += number;
220 }
221
222 //////////////////////////////////////////////////////////////////////////
223 //
224 int      Fleet::fleet(string unittype, int tick = 0)
225 {
226         int ticks = m_Fleet[unittype].size();
227         if (ticks == 0)
228                 return 0;
229
230         --ticks;
231
232         if (ticks < tick)
233                 return m_Fleet[unittype][ticks];
234
235         return m_Fleet[unittype][tick];
236 }
237
238 //////////////////////////////////////////////////////////////////////////
239 //
240 int Fleet::blockedFleet(std::string unittype, int tick = 0)
241 {
242         int ticks = m_BlockedFleet[unittype].size();
243         if (ticks == 0)
244                 return 0;
245
246         --ticks;
247
248         if (ticks < tick)
249                 return 0;
250
251         return m_BlockedFleet[unittype][tick];
252 }
253
254 //////////////////////////////////////////////////////////////////////////
255 //
256 void Fleet::setBlockedFleet(std::string unittype, int number, int tick = 0)
257 {
258         int ticks = m_BlockedFleet[unittype].size();
259
260         for (int i = ticks; i <= tick; ++i)
261         {
262                 m_BlockedFleet[unittype].push_back(0);
263         }
264         m_BlockedFleet[unittype][tick] = number;
265
266         cerr << "This fleet got " << m_BlockedFleet[unittype][tick] << " blocked units tick: " << tick << endl;
267
268 }
269
270 //////////////////////////////////////////////////////////////////////////
271 //FIXME
272 void Fleet::addToThis(std::vector<Fleet*> fleets, int tick = 0)
273 {
274         for (UnitList::iterator i = s_Units.begin();  i != s_Units.end(); ++i)
275         {
276                 if (m_Fleet[i->first].size() == 0)
277                                 m_Fleet[i->first].push_back(0);
278
279                 for (vector<Fleet*>::iterator j = fleets.begin(); j != fleets.end(); ++j)
280                 {
281                         int num = (*j)->fleet(i->first, tick);
282                         m_Fleet[i->first][0] += num;
283                         if (num > 0)
284                                 cerr << (*j)->name() <<  " adding " << num << " units of type " << i->first << endl;
285                 }
286         }
287 }
288
289 //////////////////////////////////////////////////////////////////////////
290 //
291 void Fleet::distributeLossesGains(std::vector<Fleet*> fleets, int tick = 0)
292 {
293         for (UnitList::iterator i = s_Units.begin(); i != s_Units.end(); ++i)
294         {
295                 string unittype = i->first;
296
297
298                 if (m_Fleet[unittype].size() < 1)
299                         continue;
300                 if (m_Fleet[unittype][0] == 0)
301                         continue;
302
303                  
304                 int totallost = fleet(unittype,1) - fleet(unittype, 0);
305
306
307                 cerr << "Distributing type: " << unittype << " with a total loss of " << totallost << " units" << endl;
308
309                 cerr << "Total number of units before: " << fleet(unittype, 0)  << " and after : " << fleet(unittype, 1) << endl;
310                 
311                 for (vector<Fleet*>::iterator j = fleets.begin(); j != fleets.end(); ++j)
312                 {
313                         int fl1 = (*j)->fleet(unittype, tick - 1);
314                         float part = float(fl1) / fleet(unittype, 0) ;
315                         int lost =  totallost * part;
316                         (*j)->setFleet(unittype, (*j)->fleet(unittype, tick - 1) + lost, tick);
317
318                         cerr << (*j)->name() << " gaining " << lost << " " << unittype  << " since it's " << part * 100 << "% of the whole fleet, and it had : " << fl1 << " units last tick.." <<  endl;
319
320                         lost = part * blockedFleet(unittype, 0);
321
322                         cerr << (*j)->name() << " got " << lost << " blocked " << unittype  << ", the total number of blocked ships was: " << blockedFleet(unittype, 0) << endl; 
323
324                         (*j)->setBlockedFleet(unittype, lost, tick);
325                 }
326         }
327 }
328
329 //////////////////////////////////////////////////////////////////////////
330 //
331 std::vector<Fleet*> Fleet::calculateSide(std::vector<Fleet*> fleets, int stays = 0, int tick = 0)
332 {
333         vector<Fleet*> fl;
334         for (vector<Fleet*>::iterator i = fleets.begin(); i != fleets.end(); ++i)
335         {
336                 if (( tick - (*i)->ETA()) >= 0 && (tick - (*i)->ETA()) < (*i)->stays())
337                 {
338                         fl.push_back((*i));
339                         cerr << "Using fleet " << (*i)->name() << " for tick " << tick << endl;
340                 }
341                 else if ((*i)->stays() < 0)
342                         fl.push_back((*i));
343         }
344         return fl;
345 }
346
347 //////////////////////////////////////////////////////////////////////////
348 //
349 int Fleet::freeFleet(std:: string unittype, int tick = 0)
350 {
351         int bticks = m_BlockedFleet[unittype].size();
352
353         --bticks;
354
355         if (bticks < tick)
356                 return fleet(unittype, tick);
357
358
359         int free = fleet(unittype,tick) - m_BlockedFleet[unittype][tick];
360         if (free < 0)
361                 return 0;
362         return free;
363 }
364
365
366 //////////////////////////////////////////////////////////////////////////
367 //
368 void Fleet::takeShoot(std::string unittype, int number, std::map<std::string, int>& hitunits)
369 {
370
371         float guns = s_Units[unittype].guns() * number;
372
373         
374         if (guns == 0)
375                 return;
376
377         cerr << number << " " << unittype << ": with " << guns << " guns\n";
378
379         float gunsleft = guns;
380         for (int count = 0; count < 3; ++count)//vector<string>::iterator i = s_Units[unittype].target().begin(); i != s_Units[unittype].target().end(); ++i)
381         {
382                 string ta = s_Units[unittype].target(count);
383         cerr << "Shooting at target class: " << ta << endl;
384                 while (gunsleft > 0)
385                 {
386         
387                         map<string, int*> targets;
388
389                         for (UnitList::iterator j = s_Units.begin(); j != s_Units.end(); ++j)
390                         {
391
392                                 if (m_Fleet[j->first].size() == 0)
393                                         continue;
394
395
396                                 if (m_Fleet[j->first].size() == 1 )
397                                         m_Fleet[j->first].push_back(m_Fleet[j->first][0]);
398
399                                 //cerr << "Target is class: " << j->second.type() << endl;
400
401                                 if (m_Fleet[j->first][1] > 0  && ( ta == j->second.unitClass() || ta == "All"))
402                                 {
403
404                                 //      cerr << "Looking at target: " << j->first << endl;
405                                         targets[j->first] = &m_Fleet[j->first][1];
406                                 }
407
408                         }
409
410                         if (targets.size() == 0)
411                                 break;
412
413                         int total = 0;
414                         for (map<string, int*>::iterator j = targets.begin(); j != targets.end(); ++j)
415                                 total += (*j->second);
416
417                         for (map<string, int*>::iterator j = targets.begin(); j != targets.end(); ++j)
418                         {
419                                 float maxguns = float((*j->second))/total * guns;
420                                 //cerr << "Now shooting at target: " << j->first << endl;
421
422                                 if (m_Armor[j->first] <= 0 || m_Armor[j->first] > s_Units[j->first].armor())
423                                         m_Armor[j->first] = s_Units[j->first].armor();
424                                 double k = maxguns;
425
426                                 //cerr << "Targets agility: " << s_Units[j->first].agility() << endl;
427                                 //cerr << "Weaponspeed: " << s_Units[unittype].weaponSpeed() << endl;
428                                 while (k > 0)   
429                                 {
430
431                                         if (*(j->second) <= 0)
432                                                 break;
433
434                                         int wpsp = s_Units[unittype].weaponSpeed();
435                                         int agil = s_Units[j->first].agility();
436
437                                         k -= float(100)/(25 + wpsp - agil);
438                                         //cout << "Used " << blaha << " guns to hit with one shot.\n";
439                                         //cout << "WPSP: " << wpsp << "\nAgil: " << agil << endl;
440
441                                         m_Armor[j->first] -= s_Units[unittype].power();
442                                         if (m_Armor[j->first] <= 0)
443                                         {
444                                                 m_Armor[j->first] = s_Units[j->first].armor();
445                                                 (*j->second)--;
446                                                 hitunits[j->first]++;
447                                                 
448                                                 //There is a chance that we're hitting a blocked ship.
449                                                 if (m_BlockedFleet[j->first].size() >= 1)
450                                                 {
451                                                         int test = rand() % m_BlockedFleet[j->first][0];
452                                                         if (test == 1
453                                                                 && m_BlockedFleet[j->first][0] > 0)
454                                                         {
455                                                                 if (m_BlockedFleet[j->first].size() == 1)
456                                                                         m_BlockedFleet[j->first].push_back(m_BlockedFleet[j->first][0] - 1);
457                                                                 else if (m_BlockedFleet[j->first][1] > 0)
458                                                                         m_BlockedFleet[j->first][1]--;
459                                                         }
460                                                 }
461                                         }
462
463                                 }
464
465                                 cerr << hitunits[j->first] << " units of type: " << j->first << "killed\n";
466                                 if (k <= 0)
467                                         gunsleft -= maxguns;
468                                 else
469                                         gunsleft -= maxguns - k;
470                         }
471                 }
472         }
473 }
474
475 //////////////////////////////////////////////////////////////////////////
476 //
477 void Fleet::takeEMP(std::string unittype, int number)
478 {
479         int guns = s_Units[unittype].guns() * number;
480         if (guns == 0)
481                 return;
482
483         cerr << unittype << ": with " << guns << " guns\n";
484
485         float gunsleft = guns;
486         for (int count = 0; count < 3; ++count)//vector<string>::iterator i = s_Units[unittype].target().begin(); i != s_Units[unittype].target().end(); ++i)
487         {
488                 string ta = s_Units[unittype].target(count);
489         cerr << "Shooting at target class: " << ta << endl;
490                 while (gunsleft > 0)
491                 {
492         
493                         map<string, int*> targets;
494
495                         for (UnitList::iterator j = s_Units.begin(); j != s_Units.end(); ++j)
496                         {
497                                 if (j->second.type() == "PDS")
498                                         continue;
499
500                                 if (freeFleet(j->first, 1) <= 0)
501                                         continue;
502
503                                 if (m_Fleet[j->first].size() == 0)
504                                         continue;
505
506                                 if (m_Fleet[j->first].size() == 1)
507                                         m_Fleet[j->first].push_back(m_Fleet[j->first][0]);
508
509                                 //cerr << "Target is class: " << j->second.type() << endl;
510
511                                 if (m_Fleet[j->first][1] > 0  && ( ta == j->second.unitClass() || ta == "All"))
512                                 {
513
514                                 //      cerr << "Looking at target: " << j->first << endl;
515                                         targets[j->first] = &m_Fleet[j->first][1];
516                                 }
517
518                         }
519
520                         if (targets.size() == 0)
521                                 break;
522
523                         int total = 0;
524                         for (map<string, int*>::iterator j = targets.begin(); j != targets.end(); ++j)
525                                 total += (*j->second);
526
527                         for (map<string, int*>::iterator j = targets.begin(); j != targets.end(); ++j)
528                         {
529                                 float maxguns = float((*j->second))/total * guns;
530                                 cerr << "Now shooting at target: " << j->first << endl;
531
532                                 double k = maxguns;
533
534                                 int hits = 0;
535
536                                 while (k > 0)   
537                                 {
538
539                                         if (*(j->second) <= blockedFleet(j->first, 1))
540                                                 break;
541
542                                         int eres = s_Units[j->first].EMP();
543
544                                         k -= float(100)/(100-eres);
545                                         hits++;
546                                         blockFleet(j->first, 1);
547                                 }
548
549                                 cerr << hits << " units of type: " << j->first << " blocked\n";
550                                 if (k <= 0)
551                                         gunsleft -= maxguns;
552                                 else
553                                         gunsleft -= maxguns - k;
554                         }
555                 }
556         }
557 }
558
559 //////////////////////////////////////////////////////////////////////////
560 //
561 void Fleet::killFleet(std::string unittype, int number, int tick = 0)
562 {
563         int earlier = 0;
564         int ticks = m_Fleet[unittype].size();
565
566         if (ticks != 0)
567                 earlier = m_Fleet[unittype][ticks - 1];
568
569         for (int i = ticks; i <= tick; ++i)
570         {
571                 m_Fleet[unittype].push_back(earlier);
572         }
573         m_Fleet[unittype][tick] -= number;
574 }
575
576 //////////////////////////////////////////////////////////////////////////
577 //
578 void Fleet::setResource(std::string type, int number, int tick = 0)
579 {
580
581         int ticks = m_Resources[type].size();
582         for (int i = ticks; i <= tick; ++i)
583                 m_Resources[type].push_back(number);
584         m_Resources[type][tick] = number;
585 }
586
587 //////////////////////////////////////////////////////////////////////////
588 //
589 void Fleet::addResource(std::string type, int number, int tick = 0)
590 {
591
592         int ticks = m_Resources[type].size();
593         int latest = resource(type, tick - 1);
594
595         for (int i = ticks; i <= tick; ++i)
596                 m_Resources[type].push_back(latest);
597         m_Resources[type][tick] += number;
598 }
599
600 //////////////////////////////////////////////////////////////////////////
601 //
602 int Fleet::resource(std::string type, int tick = 0) const
603 {
604         if (tick < 0)
605                 return 0;
606
607         vector<int>const* resource = 0;
608         for (ResourceList::const_iterator i = m_Resources.begin(); i != m_Resources.end(); ++i)
609         {
610                 if (i->first == type)
611                 {
612                         resource = &i->second;
613                         break;
614                 }
615         }
616         if (resource == 0)
617                 return 0;
618
619         int ticks = resource->size();
620
621         if( ticks == 0)
622                 return 0;
623
624         --ticks;
625
626         if (ticks < tick)
627                 return resource->at(ticks);
628         return resource->at(tick);
629 }
630
631 //////////////////////////////////////////////////////////////////////////
632 //
633 void Fleet::resetResources()
634 {
635         m_Resources.clear() ;   
636 }
637
638 //////////////////////////////////////////////////////////////////////////
639 //
640 void Fleet::printFleet()
641 {
642         for (UnitList::iterator i = s_Units.begin(); i != s_Units.end(); ++i)
643         {
644                 for (int tick = 0; tick < 5 ;++tick)
645                 {
646                         int num = fleet(i->first, tick);
647
648                         if (num <= 0)
649                                 break;
650                         cerr << num << " " << i->first << " during tick: " << tick << endl;
651                 }
652         }
653 }
654
655 //////////////////////////////////////////////////////////////////////////
656 //
657 void Fleet::blockFleet(std::string unittype, int number, int tick = 0)
658 {
659         if (m_BlockedFleet[unittype].size() >= 1)
660         {
661                 m_BlockedFleet[unittype][0] += number;
662                 if (m_BlockedFleet[unittype].size() > 1)
663                         m_BlockedFleet[unittype][1] += number;
664                 else
665                         m_BlockedFleet[unittype].push_back(m_BlockedFleet[unittype][0]);
666         }
667         else
668         {
669                 m_BlockedFleet[unittype].push_back(number);
670                 m_BlockedFleet[unittype].push_back(number);
671         }
672 }
673
674 //////////////////////////////////////////////////////////////////////////
675 //
676 void Fleet::distributeCappedRoids(std::vector<Fleet*> fleets, int tick = 0)
677 {
678         for (ResourceList::iterator i = m_Resources.begin(); i != m_Resources.end(); ++i)
679         {
680                 string res = i->first;
681
682
683                 cerr << "Distributing type: " << res << endl;
684                 for (vector<int>::iterator j = i->second.begin(); j != i->second.end(); ++j)
685                         cout << (*j) << endl;
686
687                 if (m_Resources[res].size() < 2)
688                         continue;
689                 if (m_Resources[res][1] == 0)
690                         continue;
691
692                  
693                 int totcapped = resource(res,1) - resource(res, 0);
694
695
696                 cerr << "Distributing type: " << res << " with a total gain of " << totcapped << " roids" << endl;
697
698                 cerr << "Total number of roids before: " << resource(res, 0)  << " and after : " << resource(res, 1) << endl;
699                 
700                 for (vector<Fleet*>::iterator j = fleets.begin(); j != fleets.end(); ++j)
701                 {
702                         unsigned fl1 = (*j)->score(tick - 1);
703                         float part = float(fl1) / score(0) ;
704                         int lost =  totcapped * part;
705
706                         cerr << (*j)->name() << " gaining " << lost << " " << res  << " since it's " << part * 100 << "% of the whole score, and it had : " << fl1 << " score last tick.. compared to fleet total of: " << score(0) <<  endl;
707
708                         //(*j)->setResource(res, (*j)->resource(res,tick-1) + lost, tick);
709                         (*j)->addResource(res,lost, tick);
710                 }
711         }
712 }
713
714 //////////////////////////////////////////////////////////////////////////
715 //
716 void Fleet::addFleet(std::map<string, int> units, int tick = 0)
717 {
718         for (map<string, int>::iterator i = units.begin(); i != units.end(); ++i)
719                 addFleet(i->first, i->second, tick);
720 }
721
722 //////////////////////////////////////////////////////////////////////////
723 //
724 int Fleet::stays() const
725 {
726         return m_iStays;
727 }
728
729 //////////////////////////////////////////////////////////////////////////
730 //
731 void Fleet::setStays(int ticks)
732 {
733         m_iStays = ticks;
734 }
735
736 //////////////////////////////////////////////////////////////////////////
737 //
738 void Fleet::calculateLostStealships(string unittype, std::map<std::string, int> stolen, int tick = 1)
739 {
740         int stealscore = 0;
741         for (map<string, int>::iterator i = stolen.begin(); i != stolen.end(); ++i)
742         {
743                 stealscore += stolen[i->first] * (s_Units[i->first].totRes() / 10.0);   
744         }
745
746         int lost = stealscore / (s_Units[unittype].totRes() / 10.0);
747
748         cerr << "Lost " << lost << " " << unittype << " due to stealing ships worth: " << stealscore << endl; 
749         killFleet(unittype, lost, tick);
750 }