File indexing completed on 2024-04-14 04:00:28

0001 /*
0002     SPDX-FileCopyrightText: 2007 Paolo Capriotti <p.capriotti@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "sea.h"
0008 #include "battlefield.h"
0009 
0010 Sea::Sea(QObject* parent, const BattleShipsConfiguration& battleShipsConfiguration)
0011 : QObject(parent)
0012 , m_size(Coord(battleShipsConfiguration.boardWidth(), battleShipsConfiguration.boardHeight()))
0013 , m_turn(PLAYER_A)
0014 , m_status(PLACING_SHIPS)
0015 , m_battle_ships_configuration(battleShipsConfiguration)
0016 {
0017     m_fields[0] = new BattleField(this, m_size, battleShipsConfiguration.isAllowedAdjacentShips());
0018     m_fields[1] = new BattleField(this, m_size, battleShipsConfiguration.isAllowedAdjacentShips());
0019 }
0020 
0021 Sea::~Sea()
0022 {
0023     m_enemyShips.clear();
0024     m_myShips.clear();
0025 
0026     delete m_fields[0];
0027     delete m_fields[1];
0028 }
0029 
0030 bool Sea::canAddShip(Player p, const Coord& pos, int size, Ship::Direction direction) const
0031 {
0032     if (m_status != PLACING_SHIPS) {
0033         return false;
0034     }
0035     return m_fields[p]->canAddShip(pos, size, direction);
0036 }
0037 
0038 bool Sea::canAddShipOfSize(Player p, int size) const
0039 {
0040     if (m_status != PLACING_SHIPS) {
0041         return false;
0042     }
0043     return m_fields[p]->canAddShipOfSize(size);
0044 }
0045 
0046 void Sea::clear(Sea::Player p)
0047 {
0048     if (m_status == PLACING_SHIPS) {
0049         m_fields[p]->clear();
0050         if(p == PLAYER_B) {
0051             m_enemyShips.clear();
0052         }
0053         else {
0054             m_myShips.clear();
0055         }
0056     }
0057     m_status = PLACING_SHIPS;
0058 }
0059 
0060 void Sea::add(Player p, Ship* ship)
0061 {
0062     if(p == PLAYER_B) {
0063         m_enemyShips.append(ship);
0064     }
0065     else {
0066         m_myShips.append(ship);
0067     }
0068 
0069     m_fields[p]->add(ship);
0070 }
0071 
0072 void Sea::add(Player p, int n)
0073 {
0074     m_fields[p]->add(n);
0075 }
0076 
0077 void Sea::addBorder(Player p, const Coord& pos)
0078 {
0079     m_fields[p]->addBorder(pos);
0080 }
0081 
0082 bool Sea::canHit(Player p, const Coord& pos) const
0083 {
0084     if (m_status != PLAYING || m_turn != p) {
0085         return false;
0086     }
0087     if (!otherField()->valid(pos)) {
0088         return false;
0089     }
0090     Element& e = otherField()->get(pos);
0091     return e.free();
0092 }
0093 
0094 HitInfo Sea::hit(const Coord& pos)
0095 {
0096     HitInfo res = otherField()->hit(pos);
0097     checkGameOver();
0098     return res;
0099 }
0100 
0101 void Sea::forceHit(const Coord& pos, const HitInfo& info)
0102 {
0103     otherField()->forceHit(pos, info);
0104     checkGameOver();
0105 }
0106 
0107 void Sea::checkGameOver()
0108 {
0109     if (otherField()->ships() <= 0) {
0110         m_status = m_turn == PLAYER_A ? A_WINS : B_WINS;
0111     }
0112     else {
0113         switchTurn();
0114     }
0115 }
0116 
0117 void Sea::allowAdjacentShips(const bool allow_adjacent_ships)
0118 {
0119     m_battle_ships_configuration.setAllowAdjacentShips(allow_adjacent_ships);
0120     m_fields[0]->setAllowAdjacentShips(allow_adjacent_ships);
0121     m_fields[1]->setAllowAdjacentShips(allow_adjacent_ships);
0122 }
0123 
0124 const Element& Sea::at(Sea::Player player, const Coord& c) const
0125 {
0126     return m_fields[player]->at(c);
0127 }
0128 
0129 bool Sea::valid(Sea::Player player, const Coord& pos) const
0130 {
0131     return m_fields[player]->valid(pos);
0132 }
0133 
0134 // Coord Sea::find(Player p, Ship* ship) const
0135 // {
0136 //     return m_fields[p]->find(ship);
0137 // }
0138 
0139 void Sea::switchTurn()
0140 {
0141     m_turn = opponent(m_turn);
0142 }
0143 
0144 Sea::Player Sea::opponent(Player p)
0145 {
0146     return p == PLAYER_A ? PLAYER_B : PLAYER_A;
0147 }
0148 
0149 void Sea::startPlaying()
0150 {
0151     Q_ASSERT(m_status == PLACING_SHIPS);
0152     m_status = PLAYING;
0153 }
0154 
0155 void Sea::abort(Player p)
0156 {
0157     if (p == PLAYER_A) {
0158         m_status = A_WINS;
0159     }
0160     else {
0161         m_status = B_WINS;
0162     }
0163 }
0164 
0165 bool Sea::isNearShip(Sea::Player p, const Coord& pos) const
0166 {
0167     return m_fields[p]->isNearShip(pos);
0168 }
0169 
0170 const QList<Ship *> Sea::enemyShips() const
0171 {
0172     return m_enemyShips;
0173 }
0174 
0175 const QList<Ship *> Sea::myShips() const
0176 {
0177     return m_myShips;
0178 }
0179 
0180 void Sea::setBattleShipsConfiguration(const BattleShipsConfiguration& configuration)
0181 {
0182     m_battle_ships_configuration=configuration;
0183     m_fields[0]->setAllowAdjacentShips(configuration.isAllowedAdjacentShips());
0184     m_fields[1]->setAllowAdjacentShips(configuration.isAllowedAdjacentShips());
0185 }
0186 
0187 #include "moc_sea.cpp"