1 /***********************************************************************
2 *
3 * Copyright (C) 2007, 2008, 2010 Graeme Gott <graeme@gottcode.org>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (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.
14 *
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/>.
17 *
18 ***********************************************************************/
19
20 #include "piece.h"
21
22 #include "board.h"
23
24 /*****************************************************************************/
25
26 static const Cell types[][4] = {
27 { Cell(0,0), Cell(0,1), Cell(0,2), Cell(0,3) },
28 { Cell(0,0), Cell(0,1), Cell(1,1), Cell(1,2) },
29 { Cell(1,0), Cell(0,1), Cell(1,1), Cell(0,2) },
30 { Cell(0,0), Cell(0,1), Cell(1,1), Cell(0,2) },
31 { Cell(0,0), Cell(1,0), Cell(1,1), Cell(1,2) },
32 { Cell(0,0), Cell(1,0), Cell(0,1), Cell(0,2) },
33 { Cell(0,0), Cell(1,0), Cell(0,1), Cell(1,1) }
34 };
35
36 /*****************************************************************************/
37
Piece(int type,Board * board)38 Piece::Piece(int type, Board* board)
39 : m_type(type),
40 m_pivot(4,1),
41 m_valid(false),
42 m_board(board)
43 {
44 Q_ASSERT(type > 0 && type < 8);
45
46 Cell position[4];
47 cells(position, type);
48 for (int i = 0; i < 4; ++i)
49 position[i].x += 4;
50
51 if (updatePosition(position))
52 m_valid = true;
53 }
54
55 /*****************************************************************************/
56
rotate()57 bool Piece::rotate()
58 {
59 if (m_type == 7) {
60 return true;
61 }
62
63 Cell rotated[4];
64 for (int i = 0; i < 4; ++i) {
65 rotated[i].x = m_pivot.x - m_pivot.y + m_cells[i].y;
66 rotated[i].y = m_pivot.x + m_pivot.y - m_cells[i].x;
67 if (rotated[i].x > 9 || rotated[i].x < 0 || rotated[i].y > 19 || rotated[i].y < 0) {
68 return false;
69 }
70 }
71
72 return updatePosition(rotated);
73 }
74
75 /*****************************************************************************/
76
drop()77 void Piece::drop()
78 {
79 for (int i = 0; i < 20; ++i)
80 moveDown();
81 }
82
83 /*****************************************************************************/
84
cells(Cell * cells,int type)85 void Piece::cells(Cell* cells, int type)
86 {
87 Q_ASSERT(cells != 0);
88 Q_ASSERT(type > 0 && type < 8);
89
90 const Cell* values = types[type - 1];
91 for (int i = 0; i < 4; ++i)
92 cells[i] = values[i];
93 }
94
95 /*****************************************************************************/
96
move(int x,int y)97 bool Piece::move(int x, int y)
98 {
99 // Move cells
100 Cell moved[4];
101 for (int i = 0; i < 4; ++i) {
102 moved[i].x = m_cells[i].x + x;
103 moved[i].y = m_cells[i].y + y;
104 if (moved[i].x > 9 || moved[i].x < 0 || moved[i].y > 19 || moved[i].y < 0)
105 return false;
106 }
107
108 bool success = updatePosition(moved);
109 if (success) {
110 m_pivot.x += x;
111 m_pivot.y += y;
112 }
113 return success;
114 }
115
116 /*****************************************************************************/
117
updatePosition(const Cell * cells)118 bool Piece::updatePosition(const Cell* cells)
119 {
120 // Check for collision of cells
121 const Cell* cell = 0;
122 for (int i = 0; i < 4; ++i) {
123 cell = &cells[i];
124 if (m_board->cell(cell->x, cell->y)) {
125 return false;
126 }
127 }
128
129 // Move cells
130 for (int i = 0; i < 4; ++i) {
131 m_cells[i] = cells[i];
132 }
133
134 return true;
135 }
136
137 /*****************************************************************************/
138