/** * Gets the coordinates of a square position * * @param string $sq square position on the board * @return array x,y coordinates */ static function _get_square_coords($sq) { #If $sq is not a valid square if (Board::square_is_valid($sq) == false) { return NULL; } $x = ord(strtolower(substr($sq, 0, 1))) - ord('a'); $y = substr($sq, 1, 1) - 1; return array($x, $y); }
/** * Takes two parameters containing the name of the square to move from and * the name of the square to move to. They should be validated with * "square_is_valid()" in Board before calling. Optionally takes a * third parameter, which can be set to zero to indicate that no legality * checking should be done. In this case, flags indicating 'en passant' pawn * captures or castling will not be set! Only by entirely validating the move * do these flags have any meaning. The default is to validate every move. * * @param string $sq1 current position of the piece * @param string $sq2 destination of the piece * @param bool $validate whether to validate the move * * @return MoveListEntry|NULL a MoveListEntry representing the move just made or NULL * if any errors occur and the move was not considered */ public function make_move($sq1, $sq2, $validate = true) { $move = NULL; #Invalid square if (Board::square_is_valid($sq1) == false) { return NULL; } if (Board::square_is_valid($sq2) == false) { return NULL; } if ($validate) { if ($this->is_move_legal($sq1, $sq2) == false) { return NULL; } } $player1 = $this->players[0]; $player2 = $this->players[1]; $board = $this->board; $piece = $board->get_piece_at($sq1); $player = $piece->get_player(); #if no piece at sq1 if ($piece == NULL) { return NULL; } $movelist = $this->movelist; $capture = $board->get_piece_at($sq2); $flags = 0x0; if ($validate && $piece instanceof Pawn) { if ($player == $player1) { if (Board::vert_distance("d8", $sq2) == 0) { $flags = $flags | self::__MOVE_PROMOTE__; } //Bitwise Or } else { if (Board::vert_distance("d1", $sq2) == 0) { $flags = $flags | self::__MOVE_PROMOTE__; } //Bitwise Or } } if ($capture) { $flags = $flags | self::__MOVE_CAPTURE__; //Bitwise Or $capture->set_captured(1); $board->set_piece_at($sq1, NULL); $board->set_piece_at($sq2, $piece); $piece->set_current_square($sq2); $piece->set_moved(1); $move = $movelist->add_move($piece, $sq1, $sq2, $flags); $movenum = $move->get_move_num(); $this->captures[$player][$movenum] = $capture; } else { if ($validate && $piece instanceof Pawn && $this->_is_valid_en_passant($piece, $sq1, $sq2)) { $last_moved = $movelist->get_last_moved(); $move = $movelist->get_move($movelist->get_move_num(), $last_moved); $capture = $move->get_piece(); $flags = $flags | self::__MOVE_CAPTURE__; $flags = $flags | self::__MOVE_EN_PASSANT__; $capture->set_captured(1); $board->set_piece_at($sq1, NULL); $board->set_piece_at($sq2, $piece); $piece->set_current_square($sq2); $move = $movelist->add_move($piece, $sq1, $sq2, $flags); $this->analyzed = 0; $movenum = $move->get_move_num(); $piece->_set_firstmoved($movenum); $this->captures[$player][$movenum] = $capture; } else { if ($validate && $piece instanceof King) { if ($this->_is_valid_short_castle($piece, $sq1, $sq2)) { $flags = $flags | self::__MOVE_CASTLE_SHORT__; } if ($this->_is_valid_long_castle($piece, $sq1, $sq2)) { $flags = $flags | self::__MOVE_CASTLE_LONG__; } } if ($flags & self::__MOVE_CASTLE_SHORT__ || $flags & self::__MOVE_CASTLE_LONG__) { $rook_sq = $king_sq = $rook_sq_new = $king_sq_new = NULL; $rook = $king = NULL; if ($player == $player1) { $rook_sq = $flags & self::__MOVE_CASTLE_SHORT__ ? "h1" : "a1"; $rook_sq_new = $flags & self::__MOVE_CASTLE_SHORT__ ? "f1" : "d1"; $king_sq = "e1"; $king_sq_new = $flags & self::__MOVE_CASTLE_SHORT__ ? "g1" : "c1"; } else { $rook_sq = $flags & self::__MOVE_CASTLE_SHORT__ ? "h8" : "a8"; $rook_sq_new = $flags & self::__MOVE_CASTLE_SHORT__ ? "f8" : "d8"; $king_sq = "e8"; $king_sq_new = $flags & self::__MOVE_CASTLE_SHORT__ ? "g8" : "c8"; } $king = $board->get_piece_at($king_sq); $rook = $board->get_piece_at($rook_sq); $board->set_piece_at($king_sq, NULL); $board->set_piece_at($king_sq_new, $king); $king->set_current_square($king_sq_new); $king->set_moved(1); $board->set_piece_at($rook_sq, NULL); $board->set_piece_at($rook_sq_new, $rook); $rook->set_current_square($rook_sq_new); $rook->set_moved(1); $move = $movelist->add_move($piece, $sq1, $sq2, $flags); $movenum = $move->get_move_num(); $this->analyzed = 0; $king->_set_firstmoved($movenum); $rook->_set_firstmoved($movenum); } else { $board->set_piece_at($sq1, NULL); $board->set_piece_at($sq2, $piece); $piece->set_current_square($sq2); $piece->set_moved(1); $move = $movelist->add_move($piece, $sq1, $sq2, $flags); $movenum = $move->get_move_num(); $piece->_set_firstmoved($movenum); } } } return $move; }