1 /*
2 SPDX-FileCopyrightText: 2003 Russell Steffen <rsteffen@bayarea.net>
3 SPDX-FileCopyrightText: 2003 Stephan Zehetner <s.zehetner@nevox.org>
4 SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com>
5 SPDX-FileCopyrightText: 2006 Inge Wallin <inge@lysator.liu.se>
6 SPDX-FileCopyrightText: 2006 Pierre Ducroquet <pinaraf@gmail.com>
7
8 SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "map.h"
12 #include "../game.h"
13 #include "../planet.h"
14 #include <cmath>
15
16
Map(int rowsCount,int colsCount)17 Map::Map(int rowsCount, int colsCount) :
18 m_rows(rowsCount),
19 m_columns(colsCount)
20 {
21 resizeMap(rowsCount, colsCount);
22 }
23
24
~Map()25 Map::~Map()
26 {
27 }
28
29
30 void
resizeMap(int rowsCount,int columnsCount)31 Map::resizeMap (int rowsCount, int columnsCount)
32 {
33 m_rows = rowsCount;
34 m_columns = columnsCount;
35 m_grid.clear();
36 m_grid = QList<QList<Sector> >();
37
38 // Initialize the grid of Sectors.
39 for (int row = 0; row < rowsCount; row++) {
40 m_grid << QList<Sector>();
41 for (int col = 0; col < columnsCount; col++) {
42 m_grid[row] << Sector(this, Coordinate(row, col));
43 connect(&m_grid[row][col], &Sector::update, this, &Map::childSectorUpdate);
44 }
45 }
46 }
47
48
49 void
addPlanet(Sector * sector,Player * player,int production,double killpercentage)50 Map::addPlanet(Sector *sector, Player *player, int production, double killpercentage)
51 {
52 new Planet(UniquePlanetName(), sector, player, production, killpercentage);
53 }
54
55
56 Planet*
addPlayerPlanetSomewhere(Player * player)57 Map::addPlayerPlanetSomewhere(Player *player)
58 {
59 Sector *sector = findRandomFreeSector();
60 if (!sector)
61 return nullptr;
62 return Planet::createPlayerPlanet(sector, player, UniquePlanetName());
63 }
64
65
66 Planet*
addNeutralPlanetSomewhere(Player * neutral)67 Map::addNeutralPlanetSomewhere(Player *neutral)
68 {
69 Sector *sector = findRandomFreeSector();
70 if (!sector)
71 return nullptr;
72 return Planet::createNeutralPlanet(sector, neutral, UniquePlanetName());
73 }
74
75
76 bool
removePlayerPlanet(Player * player)77 Map::removePlayerPlanet(Player *player)
78 {
79 for (Planet *planet : planets()) {
80 if (planet->player() == player) {
81 delete planet;
82 return true;
83 }
84 }
85 return false;
86 }
87
88
89 void
removePlayerPlanets(Player * player)90 Map::removePlayerPlanets(Player *player)
91 {
92 while(removePlayerPlanet(player)) ;
93 }
94
95
96 void
turnOverPlayerPlanets(Player * owner,Player * newOwner)97 Map::turnOverPlayerPlanets(Player* owner, Player* newOwner)
98 {
99 for (Planet *planet : planets()) {
100 if (planet->player() == owner) {
101 planet->setOwner(newOwner);
102 }
103 }
104 }
105
106
107 int
playerPlanetCount(Player * player)108 Map::playerPlanetCount(Player *player)
109 {
110 int count = 0;
111 for (Planet *planet : planets()) {
112 if (planet->player() == player) {
113 count++;
114 }
115 }
116 return count;
117 }
118
119
120 void
clearMap()121 Map::clearMap()
122 {
123 for (int x = 0; x < rows(); ++x) {
124 for (int y = 0; y < columns(); ++y) {
125 delete m_grid[x][y].planet();
126 }
127 }
128
129 Q_EMIT update();
130 }
131
132
133 QString
UniquePlanetName(void)134 Map::UniquePlanetName(void)
135 {
136 char c = 'A';
137 again:
138 for (Planet *planet : planets()) {
139 if (planet->name().at(0).toLatin1() == c) {
140 c++;
141 goto again;
142 }
143 }
144 return QChar::fromLatin1(c);
145 }
146
147
148 void
populateMap(const QList<Player * > & players,Player * neutral,int numNeutralPlanets)149 Map::populateMap(const QList<Player *> &players, Player *neutral, int numNeutralPlanets)
150 {
151 // Create a planet for each player.
152 for (Player *player : players) {
153 addPlayerPlanetSomewhere(player);
154 }
155
156 for (int x = 0; x < numNeutralPlanets; ++x) {
157 Sector *sector = findRandomFreeSector();
158 if (sector) {
159 Planet::createNeutralPlanet(sector, neutral, UniquePlanetName());
160 }
161 }
162
163 Q_EMIT update();
164 }
165
166
167 double
distance(Planet * p1,Planet * p2)168 Map::distance(Planet *p1, Planet *p2)
169 {
170 Coordinate diff = p1->sector()->coord() - p2->sector()->coord();
171
172 return sqrt(double((diff.x() * diff.x()) + (diff.y() * diff.y()))) / 2; // Yes, we're dividing by two. It's not a bug, it's a feature.
173 }
174
175
176 Sector*
findRandomFreeSector()177 Map::findRandomFreeSector()
178 {
179 for (const QList<Sector> &i : std::as_const(m_grid)) {
180 for (const Sector &j : i) {
181 if (!j.hasPlanet()) {
182 goto freesectorexists;
183 }
184 }
185 }
186
187 return nullptr;
188
189 freesectorexists:
190
191 Coordinate c;
192
193 do {
194 c = Game::generatePlanetCoordinates(rows(), columns());
195 } while (m_grid[c.x()][c.y()].hasPlanet());
196
197 return &m_grid[c.x()][c.y()];
198 }
199
200
201 void
childSectorUpdate()202 Map::childSectorUpdate()
203 {
204 Q_EMIT update();
205 }
206
207
208 const QList <Planet*>
planets()209 Map::planets()
210 {
211 QList <Planet*>planets;
212 for (const QList<Sector> &i : std::as_const(m_grid)) {
213 for (const Sector &j : i) {
214 if (j.hasPlanet()) {
215 planets += j.planet();
216 }
217 }
218 }
219 return planets;
220 }
221