Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Failed Conditions
Pull Request — master (#1072)
by Dan
05:03
created

ChessPiece::setX()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
class ChessPiece {
4
	const KING = 1;
5
	const QUEEN = 2;
6
	const ROOK = 3;
7
	const BISHOP = 4;
8
	const KNIGHT = 5;
9
	const PAWN = 6;
10
11
	public function __construct(
12
		public int $chessGameID,
13
		public int $accountID,
14
		public string $colour,
15
		public int $pieceID,
16
		public int $x,
17
		public int $y,
18
		public int $pieceNo = -1) {
19
	}
20
21
	public function isSafeMove(array &$board, array &$hasMoved, int $toX = -1, int $toY = -1) : bool {
22
		$x = $this->x;
23
		$y = $this->y;
24
		$moveInfo = ChessGame::movePiece($board, $hasMoved, $x, $y, $toX, $toY);
25
		$safe = !ChessGame::isPlayerChecked($board, $hasMoved, $this->colour);
26
		ChessGame::undoMovePiece($board, $hasMoved, $x, $y, $toX, $toY, $moveInfo);
27
		return $safe;
28
	}
29
30
	public function isAttacking(array &$board, array &$hasMoved, bool $king, int $x = -1, int $y = -1) : bool {
31
		$moves = $this->getPossibleMoves($board, $hasMoved, null, true);
32
		foreach ($moves as $move) {
33
			$p = $board[$move[1]][$move[0]];
34
			if (($move[0] == $x && $move[1] == $y) || ($king === true && $p != null && $p->pieceID == self::KING && $this->colour != $p->colour)) {
35
				return true;
36
			}
37
		}
38
		return false;
39
	}
40
41
	public function getPossibleMoves(array &$board, array &$hasMoved, int $forAccountID = null, bool $attackingCheck = false) : array {
42
		$moves = array();
43
		if ($forAccountID === null || $this->accountID == $forAccountID) {
44
			if ($this->pieceID == self::PAWN) {
45
				$dirY = $this->colour == ChessGame::PLAYER_BLACK ? 1 : -1;
46
				$moveY = $this->y + $dirY;
47
				//Pawn forward movement is not attacking - so don't check it if doing an attacking check.
48
				if (!$attackingCheck) {
49
					if (ChessGame::isValidCoord($this->x, $moveY, $board) && $board[$moveY][$this->x] === null && $this->isSafeMove($board, $hasMoved, $this->x, $moveY)) {
50
						$moves[] = array($this->x, $moveY);
51
					}
52
					$doubleMoveY = $moveY + $dirY;
53
					if ($this->y - $dirY == 0 || $this->y - $dirY * 2 == count($board)) { //Double move first move
54
						if ($board[$moveY][$this->x] === null && $board[$doubleMoveY][$this->x] === null && $this->isSafeMove($board, $hasMoved, $this->x, $doubleMoveY)) {
55
							$moves[] = array($this->x, $doubleMoveY);
56
						}
57
					}
58
				}
59
				for ($i = -1; $i < 2; $i += 2) {
60
					$moveX = $this->x + $i;
61
					if (ChessGame::isValidCoord($moveX, $moveY, $board)) {
62
						if ($attackingCheck ||
63
							((($hasMoved[ChessPiece::PAWN][0] == $moveX && $hasMoved[ChessPiece::PAWN][1] == $this->y) ||
64
							($board[$moveY][$moveX] != null && $board[$moveY][$moveX]->colour != $this->colour))
65
							&& $this->isSafeMove($board, $hasMoved, $moveX, $moveY))) {
66
							$moves[] = array($moveX, $moveY);
67
						}
68
					}
69
				}
70
			} elseif ($this->pieceID == self::KING) {
71
				for ($i = -1; $i < 2; $i++) {
72
					for ($j = -1; $j < 2; $j++) {
73
						if ($i != 0 || $j != 0) {
74
							$this->addMove($this->x + $i, $this->y + $j, $board, $moves, $hasMoved, $attackingCheck);
75
						}
76
					}
77
				}
78
				//Castling is not attacking - so don't check it if doing an attacking check.
79
				if (!$attackingCheck && !$hasMoved[$this->colour][ChessPiece::KING] && !ChessGame::isPlayerChecked($board, $hasMoved, $this->colour)) {
80
					if (!$hasMoved[$this->colour][ChessPiece::ROOK]['Queen'] &&
81
							ChessGame::isValidCoord($this->x - 1, $this->y, $board) && $board[$this->y][$this->x - 1] === null &&
82
							ChessGame::isValidCoord($this->x - 3, $this->y, $board) && $board[$this->y][$this->x - 3] === null &&
83
							$this->isSafeMove($board, $hasMoved, $this->x - 1, $this->y)) {
84
						$this->addMove($this->x - 2, $this->y, $board, $moves, $hasMoved, $attackingCheck);
85
					}
86
					if (!$hasMoved[$this->colour][ChessPiece::ROOK]['King'] &&
87
							ChessGame::isValidCoord($this->x + 1, $this->y, $board) && $board[$this->y][$this->x + 1] === null &&
88
							$this->isSafeMove($board, $hasMoved, $this->x + 1, $this->y)) {
89
						$this->addMove($this->x + 2, $this->y, $board, $moves, $hasMoved, $attackingCheck);
90
					}
91
				}
92
			} elseif ($this->pieceID == self::QUEEN) {
93
				$moveX = $this->x;
94
				$moveY = $this->y;
95
				while ($this->addMove(--$moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Left
96
				$moveX = $this->x;
97
				$moveY = $this->y;
98
				while ($this->addMove(++$moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Right
99
				$moveX = $this->x;
100
				$moveY = $this->y;
101
				while ($this->addMove($moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up
102
				$moveX = $this->x;
103
				$moveY = $this->y;
104
				while ($this->addMove($moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Down
105
				$moveX = $this->x;
106
				$moveY = $this->y;
107
				while ($this->addMove(--$moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Left
108
				$moveX = $this->x;
109
				$moveY = $this->y;
110
				while ($this->addMove(++$moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Right
111
				$moveX = $this->x;
112
				$moveY = $this->y;
113
				while ($this->addMove(--$moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Down-Left
114
				$moveX = $this->x;
115
				$moveY = $this->y;
116
				while ($this->addMove(++$moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Left
117
			} elseif ($this->pieceID == self::ROOK) {
118
				$moveX = $this->x;
119
				$moveY = $this->y;
120
				while ($this->addMove(--$moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Left
121
				$moveX = $this->x;
122
				$moveY = $this->y;
123
				while ($this->addMove(++$moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Right
124
				$moveX = $this->x;
125
				$moveY = $this->y;
126
				while ($this->addMove($moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up
127
				$moveX = $this->x;
128
				$moveY = $this->y;
129
				while ($this->addMove($moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Down
130
			} elseif ($this->pieceID == self::BISHOP) {
131
				$moveX = $this->x;
132
				$moveY = $this->y;
133
				while ($this->addMove(--$moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Left
134
				$moveX = $this->x;
135
				$moveY = $this->y;
136
				while ($this->addMove(++$moveX, --$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Right
137
				$moveX = $this->x;
138
				$moveY = $this->y;
139
				while ($this->addMove(--$moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Down-Left
140
				$moveX = $this->x;
141
				$moveY = $this->y;
142
				while ($this->addMove(++$moveX, ++$moveY, $board, $moves, $hasMoved, $attackingCheck) && $board[$moveY][$moveX] === null); //Up-Left
143
			} elseif ($this->pieceID == self::KNIGHT) {
144
				$moveX = $this->x - 1;
145
				$moveY = $this->y - 2;
146
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2up-left
147
				$moveX += 2;
148
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2up-right
149
				$moveY = $this->y + 2;
150
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2down-right
151
				$moveX -= 2;
152
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2down-left
153
				$moveX = $this->x - 2;
154
				$moveY = $this->y - 1;
155
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2left-up
156
				$moveY += 2;
157
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2left-down
158
				$moveX = $this->x + 2;
159
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2right-down
160
				$moveY -= 2;
161
				$this->addMove($moveX, $moveY, $board, $moves, $hasMoved, $attackingCheck); //2right-up
162
			}
163
		}
164
165
		return $moves;
166
	}
167
168
	private function addMove(int $toX, int $toY, array &$board, array &$moves, array &$hasMoved, bool $attackingCheck = true) : bool {
169
		if (ChessGame::isValidCoord($toX, $toY, $board)) {
170
			if (($board[$toY][$toX] === null || $board[$toY][$toX]->colour != $this->colour)) {
171
				//We can only actually move to this position if it is safe to do so, however we can pass through it looking for a safe move so we still want to return true.
172
				if (($attackingCheck === true || $this->isSafeMove($board, $hasMoved, $toX, $toY))) {
173
					$moves[] = array($toX, $toY);
174
				}
175
				return true;
176
			}
177
		}
178
		return false;
179
	}
180
181
	public function promote(int $pawnPromotionPieceID, array &$board) : array {
182
		$takenNos = array();
183
		foreach ($board as $row) {
184
			foreach ($row as $piece) {
185
				if ($piece != null && $piece->pieceID == $pawnPromotionPieceID && $piece->colour == $this->colour) {
186
					$takenNos[$piece->pieceNo] = true;
187
				}
188
			}
189
		}
190
		$i = 0;
191
		while (isset($takenNos[$i])) {
192
			$i++;
193
		}
194
		return array('PieceID' => $pawnPromotionPieceID, 'PieceNo' => $i);
195
	}
196
197
	public function getPieceLetter() : string {
198
		return self::getLetterForPiece($this->pieceID, $this->colour);
199
	}
200
201
	public function getPieceSymbol() : string {
202
		return self::getSymbolForPiece($this->pieceID, $this->colour);
203
	}
204
205
	public static function getSymbolForPiece(int $pieceID, string $colour) : string {
206
		return "&#" . (9811 + $pieceID + ($colour == ChessGame::PLAYER_WHITE ? 0 : 6)) . ";";
207
	}
208
209
	public static function getLetterForPiece(int $pieceID, string $colour) : string {
210
		$letter = match($pieceID) {
211
			self::KING => 'k',
212
			self::QUEEN => 'q',
213
			self::ROOK => 'r',
214
			self::BISHOP => 'b',
215
			self::KNIGHT => 'n',
216
			self::PAWN => 'p',
217
		};
218
		if ($colour == ChessGame::PLAYER_WHITE) {
219
			$letter = strtoupper($letter);
220
		}
221
		return $letter;
222
	}
223
224
	public static function getPieceForLetter(string $letter) : int {
225
		return match(strtolower($letter)) {
226
			'k' => self::KING,
227
			'q' => self::QUEEN,
228
			'r' => self::ROOK,
229
			'b' => self::BISHOP,
230
			'n' => self::KNIGHT,
231
			'p' => self::PAWN,
232
		};
233
	}
234
}
235