1 /*
2     SPDX-FileCopyrightText: 2007 Paolo Capriotti <p.capriotti@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "sea.h"
8 #include "battlefield.h"
9 
Sea(QObject * parent,const BattleShipsConfiguration & battleShipsConfiguration)10 Sea::Sea(QObject* parent, const BattleShipsConfiguration& battleShipsConfiguration)
11 : QObject(parent)
12 , m_size(Coord(battleShipsConfiguration.boardWidth(), battleShipsConfiguration.boardHeight()))
13 , m_turn(PLAYER_A)
14 , m_status(PLACING_SHIPS)
15 , m_battle_ships_configuration(battleShipsConfiguration)
16 {
17     m_fields[0] = new BattleField(this, m_size, battleShipsConfiguration.isAllowedAdjacentShips());
18     m_fields[1] = new BattleField(this, m_size, battleShipsConfiguration.isAllowedAdjacentShips());
19 }
20 
~Sea()21 Sea::~Sea()
22 {
23     m_enemyShips.clear();
24     m_myShips.clear();
25 
26 	delete m_fields[0];
27 	delete m_fields[1];
28 }
29 
canAddShip(Player p,const Coord & pos,int size,Ship::Direction direction) const30 bool Sea::canAddShip(Player p, const Coord& pos, int size, Ship::Direction direction) const
31 {
32     if (m_status != PLACING_SHIPS) {
33         return false;
34     }
35     return m_fields[p]->canAddShip(pos, size, direction);
36 }
37 
canAddShipOfSize(Player p,int size) const38 bool Sea::canAddShipOfSize(Player p, int size) const
39 {
40     if (m_status != PLACING_SHIPS) {
41         return false;
42     }
43     return m_fields[p]->canAddShipOfSize(size);
44 }
45 
clear(Sea::Player p)46 void Sea::clear(Sea::Player p)
47 {
48     if (m_status == PLACING_SHIPS) {
49         m_fields[p]->clear();
50         if(p == PLAYER_B) {
51             m_enemyShips.clear();
52         }
53         else {
54             m_myShips.clear();
55         }
56     }
57     m_status = PLACING_SHIPS;
58 }
59 
add(Player p,Ship * ship)60 void Sea::add(Player p, Ship* ship)
61 {
62     if(p == PLAYER_B) {
63         m_enemyShips.append(ship);
64     }
65     else {
66         m_myShips.append(ship);
67     }
68 
69     m_fields[p]->add(ship);
70 }
71 
add(Player p,int n)72 void Sea::add(Player p, int n)
73 {
74     m_fields[p]->add(n);
75 }
76 
addBorder(Player p,const Coord & pos)77 void Sea::addBorder(Player p, const Coord& pos)
78 {
79     m_fields[p]->addBorder(pos);
80 }
81 
canHit(Player p,const Coord & pos) const82 bool Sea::canHit(Player p, const Coord& pos) const
83 {
84     if (m_status != PLAYING || m_turn != p) {
85         return false;
86     }
87     if (!otherField()->valid(pos)) {
88         return false;
89     }
90     Element& e = otherField()->get(pos);
91     return e.free();
92 }
93 
hit(const Coord & pos)94 HitInfo Sea::hit(const Coord& pos)
95 {
96     HitInfo res = otherField()->hit(pos);
97     checkGameOver();
98     return res;
99 }
100 
forceHit(const Coord & pos,const HitInfo & info)101 void Sea::forceHit(const Coord& pos, const HitInfo& info)
102 {
103     otherField()->forceHit(pos, info);
104     checkGameOver();
105 }
106 
checkGameOver()107 void Sea::checkGameOver()
108 {
109     if (otherField()->ships() <= 0) {
110         m_status = m_turn == PLAYER_A ? A_WINS : B_WINS;
111     }
112     else {
113         switchTurn();
114     }
115 }
116 
allowAdjacentShips(const bool allow_adjacent_ships)117 void Sea::allowAdjacentShips(const bool allow_adjacent_ships)
118 {
119     m_battle_ships_configuration.setAllowAdjacentShips(allow_adjacent_ships);
120     m_fields[0]->setAllowAdjacentShips(allow_adjacent_ships);
121     m_fields[1]->setAllowAdjacentShips(allow_adjacent_ships);
122 }
123 
at(Sea::Player player,const Coord & c) const124 const Element& Sea::at(Sea::Player player, const Coord& c) const
125 {
126     return m_fields[player]->at(c);
127 }
128 
valid(Sea::Player player,const Coord & pos) const129 bool Sea::valid(Sea::Player player, const Coord& pos) const
130 {
131     return m_fields[player]->valid(pos);
132 }
133 
134 // Coord Sea::find(Player p, Ship* ship) const
135 // {
136 //     return m_fields[p]->find(ship);
137 // }
138 
switchTurn()139 void Sea::switchTurn()
140 {
141     m_turn = opponent(m_turn);
142 }
143 
opponent(Player p)144 Sea::Player Sea::opponent(Player p)
145 {
146     return p == PLAYER_A ? PLAYER_B : PLAYER_A;
147 }
148 
startPlaying()149 void Sea::startPlaying()
150 {
151     Q_ASSERT(m_status == PLACING_SHIPS);
152     m_status = PLAYING;
153 }
154 
abort(Player p)155 void Sea::abort(Player p)
156 {
157     if (p == PLAYER_A) {
158         m_status = A_WINS;
159     }
160     else {
161         m_status = B_WINS;
162     }
163 }
164 
isNearShip(Sea::Player p,const Coord & pos) const165 bool Sea::isNearShip(Sea::Player p, const Coord& pos) const
166 {
167     return m_fields[p]->isNearShip(pos);
168 }
169 
enemyShips() const170 const QList<Ship *> Sea::enemyShips() const
171 {
172     return m_enemyShips;
173 }
174 
myShips() const175 const QList<Ship *> Sea::myShips() const
176 {
177     return m_myShips;
178 }
179 
setBattleShipsConfiguration(const BattleShipsConfiguration & configuration)180 void Sea::setBattleShipsConfiguration(const BattleShipsConfiguration& configuration)
181 {
182     m_battle_ships_configuration=configuration;
183     m_fields[0]->setAllowAdjacentShips(configuration.isAllowedAdjacentShips());
184     m_fields[1]->setAllowAdjacentShips(configuration.isAllowedAdjacentShips());
185 }
186 
187 
188 
189 
190