SVN_SILENT made messages (.desktop file)
[kdegames.git] / kapman / ghost.cpp
blobb22ad1808cfa7ab584c46994a7590798e866c29d
1 /*
2 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
3 * Copyright 2007-2008 Alexandre Galinier <alex.galinier@hotmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "ghost.h"
20 #include "time.h"
22 #include <QPointF>
23 #include <KGameDifficulty>
24 #include <cstdlib>
26 const qreal Ghost::MAX_SPEED_RATIO = 2.0;
28 Ghost::Ghost(qreal p_x, qreal p_y, const QString & p_imageId, Maze* p_maze) : Character(p_x, p_y, p_maze) {
29 // Initialize the ghost attributes
30 m_imageId = p_imageId;
31 m_points = 200;
32 m_type = Element::GHOST;
33 m_state = Ghost::HUNTER;
34 m_maxSpeed = m_normalSpeed * MAX_SPEED_RATIO;
35 // Initialize the random-number generator
36 srand(time(NULL));
37 // Makes the ghost move as soon as the game is created
38 goLeft();
41 Ghost::~Ghost() {
45 void Ghost::goUp() {
46 m_xSpeed = 0;
47 m_ySpeed = -m_speed;
50 void Ghost::goDown() {
51 m_xSpeed = 0;
52 m_ySpeed = m_speed;
55 void Ghost::goRight() {
56 m_xSpeed = m_speed;
57 m_ySpeed = 0;
60 void Ghost::goLeft() {
61 m_xSpeed = -m_speed;
62 m_ySpeed = 0;
65 void Ghost::updateMove() {
66 // Get the current cell coordinates from the character coordinates
67 int curCellRow = m_maze->getRowFromY(m_y);
68 int curCellCol = m_maze->getColFromX(m_x);
69 // Flag to know when the ghost has no choice but go back
70 bool halfTurnRequired = true;
71 // Contains the different directions a ghost can choose when on a cell center
72 QList<QPointF> directionsList;
73 int nb = 0;
75 // If the ghost is not "eaten"
76 if (m_state != Ghost::EATEN) {
77 // If the ghost gets on a Cell center
78 if (onCenter()) {
79 // We retrieve all the directions the ghost can choose (save the turnning back)
80 if (m_maze->getCell(curCellRow, curCellCol + 1).getType() == Cell::CORRIDOR ||
81 (m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
82 m_maze->getCell(curCellRow, curCellCol + 1).getType() == Cell::GHOSTCAMP)) {
83 if (m_xSpeed >= 0) {
84 directionsList.append(QPointF(m_speed, 0.0));
85 halfTurnRequired = false;
88 if (m_maze->getCell(curCellRow + 1, curCellCol).getType() == Cell::CORRIDOR ||
89 (m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
90 m_maze->getCell(curCellRow + 1, curCellCol).getType() == Cell::GHOSTCAMP)) {
91 if (m_ySpeed >= 0) {
92 directionsList.append(QPointF(0.0, m_speed));
93 halfTurnRequired = false;
96 if (m_maze->getCell(curCellRow - 1, curCellCol).getType() == Cell::CORRIDOR ||
97 (m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
98 m_maze->getCell(curCellRow - 1, curCellCol).getType() == Cell::GHOSTCAMP)) {
99 if (m_ySpeed <= 0) {
100 directionsList.append(QPointF(0.0, -m_speed));
101 halfTurnRequired = false;
104 if (m_maze->getCell(curCellRow, curCellCol - 1).getType() == Cell::CORRIDOR ||
105 (m_maze->getCell(curCellRow, curCellCol).getType() == Cell::GHOSTCAMP &&
106 m_maze->getCell(curCellRow, curCellCol - 1).getType() == Cell::GHOSTCAMP)) {
107 if (m_xSpeed <= 0) {
108 directionsList.append(QPointF(-m_speed, 0.0));
109 halfTurnRequired = false;
112 // Random number generation to choose one of the directions
113 nb = int(double(rand()) / (double(RAND_MAX) + 1) * directionsList.size());
114 // If there is no directions in the list, the character goes backward
115 if (directionsList.size() == 0) {
116 m_xSpeed = -m_xSpeed;
117 m_ySpeed = -m_ySpeed;
118 } else if ((m_xSpeed != 0 && m_xSpeed != directionsList[nb].x()) ||
119 (m_ySpeed != 0 && m_ySpeed != directionsList[nb].y())) { // If the chosen direction isn't forward
120 // We move the ghost on the center of the cell and update the directions
121 moveOnCenter();
122 m_xSpeed = directionsList[nb].x();
123 m_ySpeed = directionsList[nb].y();
126 // We move the ghost
127 move();
128 } else { // If the ghost has been eaten
129 if (onCenter()) {
130 // If the ghost has not reached the camp yet
131 if (m_pathToCamp.size() != 0) {
132 // Go to the next cell to the camp
133 updateMove(m_pathToCamp.first().y(), m_pathToCamp.first().x());
134 // Remove the cell the ghost has reached from the path
135 m_pathToCamp.removeFirst();
136 } else {
137 // If the ghost is not at home (that means it has just been eaten)
138 if (curCellRow != m_maze->getResurrectionCell().y() || curCellCol != m_maze->getResurrectionCell().x()) {
139 // Compute the path to go back to the camp
140 m_pathToCamp = m_maze->getPathToGhostCamp(curCellRow, curCellCol);
141 if (!m_pathToCamp.isEmpty()) {
142 updateMove(m_pathToCamp.first().y(), m_pathToCamp.first().x());
143 } else {
144 // Set the ghost at home
145 m_x = m_maze->getResurrectionCell().x() * Cell::SIZE + Cell::SIZE / 2;
146 m_y = m_maze->getResurrectionCell().y() * Cell::SIZE + Cell::SIZE / 2;
147 setState(Ghost::HUNTER);
149 } else { // The ghost has reached the ghost camp
150 setState(Ghost::HUNTER);
154 move();
158 void Ghost::updateMove(int p_row, int p_col) {
159 // Get the current cell coordinates from the ghost coordinates
160 int curGhostRow = m_maze->getRowFromY(m_y);
161 int curGhostCol = m_maze->getColFromX(m_x);
163 if (onCenter()) {
164 if (curGhostRow == p_row) {
165 if (p_col > curGhostCol) {
166 m_xSpeed = m_speed;
167 m_ySpeed = 0;
168 } else {
169 m_xSpeed = -m_speed;
170 m_ySpeed = 0;
172 } else {
173 if (p_row > curGhostRow) {
174 m_xSpeed = 0;
175 m_ySpeed = m_speed;
176 } else {
177 m_xSpeed = 0;
178 m_ySpeed = -m_speed;
182 // We move the ghost
183 move();
186 QString Ghost::getImageId() const {
187 return m_imageId;
190 Ghost::State Ghost::getState() const {
191 return m_state;
194 void Ghost::setState(Ghost::State p_state) {
195 // Change the state
196 m_state = p_state;
197 switch (m_state) {
198 case Ghost::PREY:
199 m_speed = m_normalSpeed / 2;
200 break;
201 case HUNTER:
202 case EATEN:
203 m_speed = m_normalSpeed;
204 break;
206 emit(stateChanged());
209 void Ghost::doActionOnCollision(Kapman*) {
210 switch (m_state) {
211 case Ghost::HUNTER:
212 emit(lifeLost());
213 break;
214 case Ghost::PREY:
215 emit(ghostEaten(this));
216 break;
217 case Ghost::EATEN:
218 // Do nothing
219 break;
223 void Ghost::initSpeedInc() {
224 // Ghosts speed increase when level up
225 if(KGameDifficulty::level() == KGameDifficulty::Easy) {
226 m_speedIncrease = Character::LOW_SPEED_INC;
228 if(KGameDifficulty::level() == KGameDifficulty::Medium) {
229 m_speedIncrease = Character::MEDIUM_SPEED_INC;
231 if(KGameDifficulty::level() == KGameDifficulty::Hard) {
232 m_speedIncrease = Character::HIGH_SPEED_INC;