File indexing completed on 2024-03-24 04:04:42
0001 /* 0002 KBlackBox - A simple game inspired by an emacs module 0003 0004 SPDX-FileCopyrightText: 1999-2000 Robert Cimrman <cimrman3@students.zcu.cz> 0005 SPDX-FileCopyrightText: 2007 Nicolas Roffet <nicolas-kde@roffet.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 0011 #include "kbbballsonboard.h" 0012 0013 0014 0015 #include "kbbgamedoc.h" 0016 0017 0018 0019 // 0020 // Constructor / Destructor 0021 // 0022 0023 KBBBallsOnBoard::KBBBallsOnBoard(KBBGameDoc* parent, const int columns, const int rows) : QObject(parent) 0024 { 0025 m_columns = columns; 0026 m_rows = rows; 0027 } 0028 0029 0030 0031 // 0032 // Public 0033 // 0034 0035 int KBBBallsOnBoard::absolutePositionToBorderPosition(int position[DIM_MAX]) 0036 { 0037 int borderPosition = KBBGameDoc::HIT_POSITION; 0038 if (position[DIM_Y] == 1) 0039 borderPosition = position[DIM_X] - 2; 0040 else if (position[DIM_X] == m_columns + 2) 0041 borderPosition = position[DIM_Y] - 2 + m_columns; 0042 else if (position[DIM_Y] == m_rows + 2) 0043 borderPosition = 1 - position[DIM_X] + 2 * m_columns + m_rows; 0044 else if (position[DIM_X] == 1) 0045 borderPosition = 1 - position[DIM_Y] + 2*(m_rows + m_columns); 0046 0047 return borderPosition; 0048 } 0049 0050 0051 int KBBBallsOnBoard::absolutePositionToBoxPosition(int position[DIM_MAX]) 0052 { 0053 return (position[DIM_X]-2)+(position[DIM_Y]-2)*(m_columns); 0054 } 0055 0056 0057 void KBBBallsOnBoard::add(int boxPosition) 0058 { 0059 m_balls.append(boxPosition); 0060 Q_EMIT changes(); 0061 } 0062 0063 0064 void KBBBallsOnBoard::borderPositionToAbsolutePosition(int borderPosition, int position[DIM_MAX]) 0065 { 0066 if (borderPosition < m_columns) { 0067 position[DIM_X] = borderPosition + 2; 0068 position[DIM_Y] = 1; 0069 } else if ((borderPosition >= m_columns) && (borderPosition < m_columns + m_rows)) { 0070 position[DIM_X] = m_columns + 2; 0071 position[DIM_Y] = (borderPosition - m_columns) + 2; 0072 } else if ((borderPosition >= m_columns + m_rows) && (borderPosition < 2*m_columns + m_rows)) { 0073 position[DIM_X] = (m_columns - (borderPosition - m_columns - m_rows)) + 1; 0074 position[DIM_Y] = m_rows + 2; 0075 } else if (borderPosition >= 2*m_columns + m_rows) { 0076 position[DIM_X] = 1; 0077 position[DIM_Y] = (m_rows - (borderPosition - 2*m_columns - m_rows)) + 1; 0078 } else { 0079 position[DIM_X] = KBBGameDoc::HIT_POSITION; 0080 position[DIM_Y] = KBBGameDoc::HIT_POSITION; 0081 } 0082 } 0083 0084 0085 int KBBBallsOnBoard::columns() 0086 { 0087 return m_columns; 0088 } 0089 0090 0091 bool KBBBallsOnBoard::contains(int boxPosition) 0092 { 0093 return m_balls.contains(boxPosition); 0094 } 0095 0096 0097 int KBBBallsOnBoard::count() 0098 { 0099 return m_balls.count(); 0100 } 0101 0102 0103 void KBBBallsOnBoard::newBoard(const int columns, const int rows) 0104 { 0105 m_balls.clear(); 0106 m_columns = columns; 0107 m_rows = rows; 0108 Q_EMIT changes(); 0109 } 0110 0111 0112 int KBBBallsOnBoard::numberOfBallsNotIn(KBBBallsOnBoard* otherBoard) 0113 { 0114 int diff = 0; 0115 0116 for (int i=0; i<m_balls.count(); i++) 0117 if (!otherBoard->contains(m_balls[i])) 0118 diff++; 0119 0120 return diff; 0121 } 0122 0123 0124 int KBBBallsOnBoard::oppositeBorderPosition(int borderPosition) { 0125 QList<int> points; 0126 return oppositeBorderPositionWithPoints(borderPosition, points); 0127 } 0128 0129 0130 int KBBBallsOnBoard::oppositeBorderPositionWithPoints(const int borderPosition, QList<int> &points) { 0131 // 1. Conversion "border position -> (Absolute) position" 0132 int position[DIM_MAX]; 0133 borderPositionToAbsolutePosition(borderPosition, position); 0134 0135 // 2. Get start direction 0136 int direction[DIM_MAX]; 0137 if (borderPosition < m_columns) { 0138 direction[DIM_X] = 0; 0139 direction[DIM_Y] = 1; 0140 } else if ((borderPosition >= m_columns) && (borderPosition < m_columns + m_rows)) { 0141 direction[DIM_X] = -1; 0142 direction[DIM_Y] = 0; 0143 } else if ((borderPosition >= m_columns + m_rows) && (borderPosition < 2*m_columns + m_rows)) { 0144 direction[DIM_X] = 0; 0145 direction[DIM_Y] = -1; 0146 } else if (borderPosition >= 2*m_columns + m_rows) { 0147 direction[DIM_X] = 1; 0148 direction[DIM_Y] = 0; 0149 } 0150 0151 // 3. Get the outgoing (absolute) position 0152 getOutgoingPosition(position, direction, points); 0153 0154 // 4. Conversion "(absolute) position -> border position" 0155 return absolutePositionToBorderPosition(position); 0156 } 0157 0158 0159 void KBBBallsOnBoard::ray(const int borderPosition, QList<int> &points) 0160 { 0161 oppositeBorderPositionWithPoints(borderPosition, points); 0162 } 0163 0164 0165 void KBBBallsOnBoard::remove(int boxPosition) 0166 { 0167 m_balls.removeAll(boxPosition); 0168 Q_EMIT changes(); 0169 } 0170 0171 0172 int KBBBallsOnBoard::rows() 0173 { 0174 return m_rows; 0175 } 0176 0177 0178 0179 // 0180 // Private 0181 // 0182 0183 void KBBBallsOnBoard::getOutgoingPosition( int position[DIM_MAX], int incomingDirection[DIM_MAX], QList<int> &points) 0184 { 0185 int outgoingDirection[DIM_MAX]; 0186 0187 int nextPosition[DIM_MAX]; 0188 nextPosition[DIM_X] = position[DIM_X] + incomingDirection[DIM_X]; 0189 nextPosition[DIM_Y] = position[DIM_Y] + incomingDirection[DIM_Y]; 0190 0191 int nextLeftPosition[DIM_MAX]; 0192 nextLeftPosition[DIM_X] = nextPosition[DIM_X] + incomingDirection[DIM_Y]; 0193 nextLeftPosition[DIM_Y] = nextPosition[DIM_Y] + incomingDirection[DIM_X]; 0194 0195 int nextRightPosition[DIM_MAX]; 0196 nextRightPosition[DIM_X] = nextPosition[DIM_X] - incomingDirection[DIM_Y]; 0197 nextRightPosition[DIM_Y] = nextPosition[DIM_Y] - incomingDirection[DIM_X]; 0198 0199 bool deviation = false; 0200 if (positionInTheBox(nextPosition) && contains((nextPosition[DIM_X] - 2) + (nextPosition[DIM_Y] - 2) * m_columns)) { 0201 // HIT 0202 position[DIM_X] = KBBGameDoc::HIT_POSITION; 0203 position[DIM_Y] = KBBGameDoc::HIT_POSITION; 0204 points.append(absolutePositionToBoxPosition(nextPosition)); 0205 } else if (positionInTheBox(nextLeftPosition) && contains((nextLeftPosition[DIM_X] - 2) + (nextLeftPosition[DIM_Y] - 2) * m_columns)) { 0206 // DEVIATION 1 0207 outgoingDirection[DIM_X] = -incomingDirection[DIM_Y]; 0208 outgoingDirection[DIM_Y] = -incomingDirection[DIM_X]; 0209 deviation = true; 0210 } else if (positionInTheBox(nextRightPosition) && contains((nextRightPosition[DIM_X] - 2) + (nextRightPosition[DIM_Y] - 2) * m_columns)) { 0211 // DEVIATION 2 0212 outgoingDirection[DIM_X] = incomingDirection[DIM_Y]; 0213 outgoingDirection[DIM_Y] = incomingDirection[DIM_X]; 0214 deviation = true; 0215 } else { 0216 //NORMAL 0217 position[DIM_X] = nextPosition[DIM_X]; 0218 position[DIM_Y] = nextPosition[DIM_Y]; 0219 outgoingDirection[DIM_X] = incomingDirection[DIM_X]; 0220 outgoingDirection[DIM_Y] = incomingDirection[DIM_Y]; 0221 } 0222 0223 // Out of the Black box? (loop exit condition) 0224 if (positionInTheBox(position)) { 0225 points.append(absolutePositionToBoxPosition(position)); 0226 getOutgoingPosition( position, outgoingDirection, points ); 0227 } else if (deviation) 0228 // special case: Deviation entering the black box. Player should see the laser ray entering, even if it's in fact deviated before entering... 0229 points.append(absolutePositionToBoxPosition(nextPosition)); 0230 0231 return; 0232 } 0233 0234 0235 bool KBBBallsOnBoard::positionInTheBox( int position[DIM_MAX] ) 0236 { 0237 return !((position[DIM_X] < 2) || (position[DIM_X] > m_columns + 1) || (position[DIM_Y] < 2) || (position[DIM_Y] > m_rows + 1)); 0238 } 0239 0240 #include "moc_kbbballsonboard.cpp"