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
Push — master ( 9c91a5...05804d )
by Dan
33s queued 16s
created

ChessPiece::getX()   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 0
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