Warning, file /games/kapman/src/maze.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
0003     SPDX-FileCopyrightText: 2007-2008 Pierre-BenoƮt Besse <besse.pb@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "maze.h"
0009 
0010 #include <QDebug>
0011 #include <cmath>
0012 
0013 Maze::Maze()
0014     : m_totalNbElem(0)
0015     , m_nbElem(0)
0016 {
0017 }
0018 
0019 Maze::~Maze()
0020 {
0021     for (int i = 0; i < m_nbRows; ++i) {
0022         delete[] m_cells[i];
0023     }
0024     delete[] m_cells;
0025 }
0026 
0027 void Maze::init(const int p_nbRows, const int p_nbColumns)
0028 {
0029     m_nbRows = p_nbRows;
0030     m_nbColumns = p_nbColumns;
0031     m_cells = new Cell *[m_nbRows];
0032     for (int i = 0; i < m_nbRows; ++i) {
0033         m_cells[i] = new Cell[m_nbColumns];
0034     }
0035 }
0036 
0037 void Maze::setCellType(const int p_row, const int p_column, const Cell::Type p_type)
0038 {
0039     if (p_row < 0 || p_row >= m_nbRows || p_column < 0 || p_column >= m_nbColumns) {
0040         qCritical() << "Bad maze coordinates";
0041     }
0042     m_cells[p_row][p_column].setType(p_type);
0043 }
0044 
0045 void Maze::setCellElement(const int p_row, const int p_column, Element *p_element)
0046 {
0047     if (p_row < 0 || p_row >= m_nbRows || p_column < 0 || p_column >= m_nbColumns) {
0048         qCritical() << "Bad maze coordinates";
0049     }
0050     m_cells[p_row][p_column].setElement(p_element);
0051     if (p_element != nullptr) {
0052         m_totalNbElem++;
0053         m_nbElem++;
0054     }
0055 }
0056 
0057 void Maze::setResurrectionCell(QPoint p_resurrectionCell)
0058 {
0059     // TODO : COORDINATES INVERTED, NEED TO CORRECT IT in the findPAth algorithm
0060     m_resurrectionCell.setX(p_resurrectionCell.y());
0061     m_resurrectionCell.setY(p_resurrectionCell.x());
0062 }
0063 
0064 void Maze::decrementNbElem()
0065 {
0066     m_nbElem--;
0067     if (m_nbElem == 0) {
0068         Q_EMIT allElementsEaten();
0069     }
0070 }
0071 
0072 void Maze::resetNbElem()
0073 {
0074     m_nbElem = m_totalNbElem;
0075 }
0076 
0077 QList<QPoint> Maze::getPathToGhostCamp(const int p_row, const int p_column) const
0078 {
0079     QList<QPoint> path;
0080     QList<QPoint> openList;
0081     QList<QPoint> closedList;
0082     QPoint currentCell;
0083     QPoint tmpCell;
0084     int lowestCost;
0085     int icurrent = 0;
0086     int oldSize = 0;
0087 
0088     // Initialize the starting cell
0089     m_cells[p_row][p_column].setCost(abs(m_resurrectionCell.y() - p_row) + abs(m_resurrectionCell.x() - p_column));
0090     // Add the starting cell to the openList
0091     openList.append(QPoint(p_column, p_row));
0092     // While the closed list does not contain the target cell
0093     while (!closedList.contains(QPoint(m_resurrectionCell.x(), m_resurrectionCell.y())) && openList.size() != oldSize) {
0094         // Look for the lowest cost cell on the open list
0095         lowestCost = 1000;
0096         for (int i = 0; i < openList.size(); ++i) {
0097             if (m_cells[openList[i].y()][openList[i].x()].getCost() < lowestCost) {
0098                 lowestCost = m_cells[openList[i].y()][openList[i].x()].getCost();
0099                 currentCell = openList[i];
0100                 icurrent = i;
0101             }
0102         }
0103         // Switch this cell to the closed list
0104         closedList.append(currentCell);
0105         openList.removeAt(icurrent);
0106         oldSize = openList.size();
0107         // For each of the 4 cells adjacent to the current node
0108         // Left
0109         tmpCell.setX(currentCell.x() - 1);
0110         tmpCell.setY(currentCell.y());
0111         if (m_cells[tmpCell.y()][tmpCell.x()].getType() != Cell::WALL) {
0112             // If the cell is not in the closed list or the open list
0113             if (!closedList.contains(tmpCell) && !openList.contains(tmpCell)) {
0114                 // Initialize the cell
0115                 m_cells[tmpCell.y()][tmpCell.x()].setCost(abs(m_resurrectionCell.y() - tmpCell.y()) + abs(m_resurrectionCell.x() - (tmpCell.x())));
0116                 m_cells[tmpCell.y()][tmpCell.x()].setParent(&m_cells[currentCell.y()][currentCell.x()]);
0117                 // Add it to the open list
0118                 openList.append(tmpCell);
0119             }
0120         }
0121         // Right
0122         tmpCell.setX(currentCell.x() + 1);
0123         tmpCell.setY(currentCell.y());
0124         if (m_cells[tmpCell.y()][tmpCell.x()].getType() != Cell::WALL) {
0125             // If the cell is not in the closed list or the open list
0126             if (!closedList.contains(tmpCell) && !openList.contains(tmpCell)) {
0127                 // Initialize the cell
0128                 m_cells[tmpCell.y()][tmpCell.x()].setCost(abs(m_resurrectionCell.y() - tmpCell.y()) + abs(m_resurrectionCell.x() - (tmpCell.x())));
0129                 m_cells[tmpCell.y()][tmpCell.x()].setParent(&m_cells[currentCell.y()][currentCell.x()]);
0130                 // Add it to the open list
0131                 openList.append(tmpCell);
0132             }
0133         }
0134         // Top
0135         tmpCell.setX(currentCell.x());
0136         tmpCell.setY(currentCell.y() - 1);
0137         if (m_cells[tmpCell.y()][tmpCell.x()].getType() != Cell::WALL) {
0138             // If the cell is not in the closed list or the open list
0139             if (!closedList.contains(tmpCell) && !openList.contains(tmpCell)) {
0140                 // Initialize the cell
0141                 m_cells[tmpCell.y()][tmpCell.x()].setCost(abs(m_resurrectionCell.y() - tmpCell.y()) + abs(m_resurrectionCell.x() - (tmpCell.x())));
0142                 m_cells[tmpCell.y()][tmpCell.x()].setParent(&m_cells[currentCell.y()][currentCell.x()]);
0143                 // Add it to the open list
0144                 openList.append(tmpCell);
0145             }
0146         }
0147         // Bottom
0148         tmpCell.setX(currentCell.x());
0149         tmpCell.setY(currentCell.y() + 1);
0150         if (m_cells[tmpCell.y()][tmpCell.x()].getType() != Cell::WALL) {
0151             // If the cell is not in the closed list or the open list
0152             if (!closedList.contains(tmpCell) && !openList.contains(tmpCell)) {
0153                 // Initialize the cell
0154                 m_cells[tmpCell.y()][tmpCell.x()].setCost(abs(m_resurrectionCell.y() - tmpCell.y()) + abs(m_resurrectionCell.x() - (tmpCell.x())));
0155                 m_cells[tmpCell.y()][tmpCell.x()].setParent(&m_cells[currentCell.y()][currentCell.x()]);
0156                 // Add it to the open list
0157                 openList.append(tmpCell);
0158             }
0159         }
0160     }
0161     if (oldSize == openList.size()) {
0162         qCritical() << "Path to ghost home not found";
0163         return {};
0164     }
0165     // Save the path : from the target cell, go from each cell to its parent cell until reaching the starting cell
0166     for (Cell *cell = &m_cells[m_resurrectionCell.y()][m_resurrectionCell.x()]; cell->getParent() != &m_cells[p_row][p_column]; cell = cell->getParent()) {
0167         path.prepend(getCoords(cell));
0168     }
0169 
0170     return path;
0171 }
0172 
0173 Cell Maze::getCell(const int p_row, const int p_column) const
0174 {
0175     if (p_row < 0 || p_row >= m_nbRows || p_column < 0 || p_column >= m_nbColumns) {
0176         qCritical() << "Bad maze coordinates";
0177     }
0178     return m_cells[p_row][p_column];
0179 }
0180 
0181 QPoint Maze::getCoords(Cell *p_cell) const
0182 {
0183     for (int i = 0; i < m_nbRows; ++i) {
0184         for (int j = 0; j < m_nbColumns; ++j) {
0185             if (&m_cells[i][j] == p_cell) {
0186                 return {j, i};
0187             }
0188         }
0189     }
0190     return {};
0191 }
0192 
0193 int Maze::getRowFromY(const qreal p_y) const
0194 {
0195     return (int)(p_y / Cell::SIZE);
0196 }
0197 
0198 int Maze::getColFromX(const qreal p_x) const
0199 {
0200     return (int)(p_x / Cell::SIZE);
0201 }
0202 
0203 int Maze::getNbColumns() const
0204 {
0205     return m_nbColumns;
0206 }
0207 
0208 int Maze::getNbRows() const
0209 {
0210     return m_nbRows;
0211 }
0212 
0213 int Maze::getNbElem() const
0214 {
0215     return m_nbElem;
0216 }
0217 
0218 int Maze::getTotalNbElem() const
0219 {
0220     return m_totalNbElem;
0221 }
0222 
0223 QPoint Maze::getResurrectionCell() const
0224 {
0225     return m_resurrectionCell;
0226 }
0227 
0228 #include "moc_maze.cpp"