<?php
/**
* PHPChess 1.0
*
* Online chess game
*
* @author: Carlos Reche
* @e-mail: hide@address.com
*
* Jan 31, 2005
*
*
*
* Feb 7, 05 - bug reported and fixed by Ulrik S. Kofod,
* on function PHPChess_Board::movePiece(), line 451
* Feb 8, 05 - grammars corrections sent by Randy Rowe
* Mar 14, 06 - bug reported and fixed by Pablo Díaz Anzalone and
* João Antônio Navarini, when runing on servers with
* "magic quotes" activated.
*/
/**
* class PHPChess
*
* Main class. Will control all functionalities of the other classes.
*/
class PHPChess
{
/*@#+
* @access private
*/
var $board; // (object) Board object. Contains all informations of the board squares and pieces
var $interface; // (object) Displays the chess board and HTML form
//@#+
/*
* @function PHPChess()
*
* @access public
*
* Contructor.
*/
function PHPChess()
{
$this->board = new PHPChess_Board();
$this->interface = new PHPChess_Interface($this->board);
if (isset($_POST['white']))
{
$this->board->white->email = trim($_POST['white']);
}
if (isset($_POST['black']))
{
$this->board->black->email = trim($_POST['black']);
}
if (isset($_POST['mov_start'], $_POST['mov_end']))
{
if (preg_match("/^[A-H][1-8]$/i", $_POST['mov_start']) && preg_match("/^[A-H][1-8]$/i", $_POST['mov_end']))
{
$x_start = $this->interface->valueOfX($_POST['mov_start']{0});
$y_start = $_POST['mov_start']{1};
$x_end = $this->interface->valueOfX($_POST['mov_end']{0});
$y_end = $_POST['mov_end']{1};
$this->confirmMove($x_start, $y_start, $x_end, $y_end);
}
else
{
$this->interface->error("Invalid move: <strong>" . $_POST['mov_start'] . $_POST['mov_end'] . "</strong>");
}
}
}
/*
* @function setImageDir( string $dir )
*
* @access public
*
* Defines a directory for pieces images. It must be a valid directory, and image names
* should be: "white_king.png", "black_king.png", "white_queen.png" etc.
* Pieces names are "king", "queen", "bishop", "knight", "rook" and "pawn".
*/
function setImageDir($dir)
{
$dir = (string)$dir;
if (!is_dir($dir))
{
$this->interface->error("Image dir does not exist.");
return false;
}
if (!preg_match("/^.*?\\/$/", $dir))
{
$dir .= "/";
}
$this->interface->image_dir = $dir;
return true;
}
/*
* @function showCoordinates( bool $show )
*
* @access public
*
* Sets if should display the square coordinates
*/
function showCoordinates($show = true)
{
$this->interface->show_coordinates = (bool)$show;
}
/*
* @function squareSize( bool $show )
*
* @access public
*
* Sets the size (in pixels) of the board squares
*/
function squareSize($size)
{
$this->interface->square_size = (int)$size;
}
/*
* @function board( [ bool $return ] )
*
* @access public
*
* Prints the HTML code of the board. If you want the HTML code to be returned as a string,
* not printed, set the boolean parameter $return to TRUE.
*/
function board($bool_return = false)
{
return $this->interface->board($bool_return);
}
/*
* @function form( [ bool $return ] )
*
* @access public
*
* Prints the HTML code of the form. If you want the HTML code to be returned as a string,
* not printed, set the boolean parameter $return to TRUE.
*/
function form($bool_return = false)
{
return $this->interface->form($bool_return);
}
/*
* @function message( [ bool $return ] )
*
* @access public
*
* Prints a message from the system.
*/
function message($bool_return = false)
{
return $this->interface->message($bool_return);
}
/*
* @function setSMTP [ bool $return ] )
*
* @access public
*
* Defines a SMTP server to send emails.
*/
function setSMTP($smtp)
{
$this->interface->setSMTP($smtp);
}
/*
* @function confirmMove( int $x_start, int $y_start, int $x_end, int $y_end )
*
* @access private
*
* Called in class constructor if player has moved a piece.
*/
function confirmMove($x_start, $y_start, $x_end, $y_end)
{
$mail_pattern = "/^\s*[\w\d]+([.-][\w\d]+)*@[\w\d]+([.-][\w\d]+)*\\.[\w\d]{2,4}\s*$/i";
if (!preg_match($mail_pattern, $this->board->white->email) || !preg_match($mail_pattern, $this->board->black->email))
{
$this->interface->setMessage("<strong>Error!</strong> There seems to be at least one invalid email address!");
return false;
}
$square =& $this->board->square[$x_start][$y_start];
$piece =& $square->piece;
if (!$square->hasPiece() || ($piece->color != $this->board->turn()))
{
$this->interface->setMessage("Please move a <strong>" . $this->board->turn() . "</strong> piece.");
return false;
}
else if (!$piece->validateMove($this->board, $x_end, $y_end))
{
$move = $this->interface->valueOfX($x_start) . $y_start . $this->interface->valueOfX($x_end) . $y_end;
$this->interface->setMessage("<strong>Notice!</strong> " . $move . " is not a valid move.");
return false;
}
else if (!$this->board->movePiece($x_start, $y_start, $x_end, $y_end))
{
$this->interface->setMessage("<strong>Notice!</strong> Your King can not be on a square controlled by the opponent.");
return false;
}
$this->board->has_moved = true;
$this->board->verifyCheckMate();
return true;
}
}
class PHPChess_Board
{
var $square; // (array) Multi-dimensional array of objects (type: PHPChess_Square)
var $white; // (object) White player (type: PHPChess_Player)
var $black; // (object) Black player (type: PHPChess_Player)
var $user; // (object) Alias to $white or $black, depending of the turn
var $opponent; // (object) Alias to $white or $black, depending of the turn
var $history; // (array) Game history
var $removed_piece; // (object) Reference to the object of the last removed piece, or false if the square was empty
var $has_moved; // (bool) Will be "true" if the player has maden a move, or "false" if hasn't.
var $is_check; // (bool) Will be "true" if $user King is under attack
var $is_check_mate; // (bool) Will be "true" if $user capture $opponent's King
var $is_stalemate; // (bool) If the player who must move has no legal move (and is NOT in check), the game ends as a draw (a stalemate)
function PHPChess_Board()
{
$this->square = array();
$this->white = new PHPChess_Player("white");
$this->black = new PHPChess_Player("black");
$this->user =& $this->white;
$this->opponent =& $this->black;
$this->history = array();
$this->removed_piece = false;
$this->has_moved = false;
$this->is_check = false;
$this->is_check_mate = false;
$this->is_draw = false;
// Fill array $this->square with objects (type: PHPChess_Square)
for ($x = 1; $x <= 8; $x++)
{
if (!isset($this->square[$x]))
{
$this->square[$x] = array();
}
for ($y = 1; $y <= 8; $y++)
{
$this->square[$x][$y] = new PHPChess_Square($x, $y);
}
}
// Adds pieces to the square objects (default start positions)
$this->addRook("black", 1, 8);
$this->addKnight("black", 2, 8);
$this->addBishop("black", 3, 8);
$this->addQueen("black", 4, 8);
$this->addKing("black", 5, 8);
$this->addBishop("black", 6, 8);
$this->addKnight("black", 7, 8);
$this->addRook("black", 8, 8);
$this->addRook("white", 1, 1);
$this->addKnight("white", 2, 1);
$this->addBishop("white", 3, 1);
$this->addQueen("white", 4, 1);
$this->addKing("white", 5, 1);
$this->addBishop("white", 6, 1);
$this->addKnight("white", 7, 1);
$this->addRook("white", 8, 1);
for ($i = 1; $i <= 8; $i++)
{
$this->addPawn("black", $i, 7);
$this->addPawn("white", $i, 2);
}
if (isset($_GET['game_data']))
{
$this->unpackData($_GET['game_data']);
}
$this->updateData();
}
function turn($this_user = true)
{
return ((count($this->history) % 2 == (($this_user) ? 0 : 1)) ? "white" : "black");
}
function movePiece($x_start, $y_start, $x_end, $y_end, $really_move = true)
{
if (!$this->square[$x_start][$y_start]->hasPiece())
{
return false;
}
// Grabs the pieces, removing them from the board
$piece_mov =& $this->removePiece($x_start, $y_start);
$piece_cap =& $this->removePiece($x_end, $y_end);
// Checks for "en passant" capture
if ($piece_mov->isPawn() && (abs($x_start - $x_end) == 1) && !$piece_cap)
{
$piece_cap =& $this->removePiece($x_end, $y_start);
}
// Puts the piece on the target square
$this->square[$x_end][$y_end]->piece =& $piece_mov;
// Updates the squares controlled by the opponent
$this->updateData();
// Checks if the King did not stay on a square that is under attack by moving the piece
if (!$piece_mov->isKing())
{
$king =& $this->{$piece_mov->color}->pieces['king'];
$king_square =& $this->square[$king->x][$king->y];
}
else
{
$king_square =& $this->square[$x_end][$y_end];
}
foreach ($king_square->controlled_by as $p)
{
if ($p->color != $piece_mov->color)
{
$this->removePiece($x_end, $y_end);
$this->square[$piece_mov->x][$piece_mov->y]->piece =& $piece_mov;
if ($piece_cap)
{
$this->square[$piece_cap->x][$piece_cap->y]->piece =& $piece_cap;
}
return false;
}
}
// If was only checking
if (!$really_move)
{
$this->removePiece($x_end, $y_end);
$this->square[$piece_mov->x][$piece_mov->y]->piece =& $piece_mov;
if ($piece_cap)
{
$this->square[$piece_cap->x][$piece_cap->y]->piece =& $piece_cap;
}
return true;
}
$this->removed_piece =& $piece_cap;
$piece_mov->x = $x_end;
$piece_mov->y = $y_end;
$piece_mov->num_moves++;
/**
* bug reported and fixed by Ulrik S. Kofod
* Feb 9, 2005
*
* if your king were under attack, there was an specific situation
* that let you move another piece even if your king still were under
* check.
*/
if ($piece_mov->isKing())
{
$this->{$piece_mov->color}->pieces['king']->x = $x_end;
$this->{$piece_mov->color}->pieces['king']->y = $y_end;
}
// Checks for "castling"
if ($piece_mov->isKing() && (abs($x_start - $x_end) == 2))
{
if ($x_start > $x_end)
{
$rook =& $this->removePiece(1, $piece_mov->y);
$this->square[4][$piece_mov->y]->piece =& $rook;
$rook->x = 4;
}
else
{
$rook =& $this->removePiece(8, $piece_mov->y);
$this->square[6][$piece_mov->y]->piece =& $rook;
$rook->x = 6;
}
$rook->num_moves++;
}
// Checks for "queening"
else if ($piece_mov->isPawn() && (($piece_mov->y == 1) || ($piece_mov->y == 8)))
{
$this->addQueen($piece_mov->color, $piece_mov->x, $piece_mov->y, $piece_mov->num_moves);
}
$this->history[] = $x_start . $y_start . $x_end . $y_end;
return true;
}
function removePiece($x, $y)
{
$removed_piece =& $this->square[$x][$y]->piece;
// Destroys only the square reference to the piece, without changing the piece value to "false"
unset($this->square[$x][$y]->piece);
$this->square[$x][$y]->piece = false;
return $removed_piece;
}
function verifyCheckMate()
{
$this->is_check = false;
$this->is_check_mate = false;
$this->is_draw = false;
$player =& $this->{$this->turn()};
$king =& $player->pieces['king'];
$king_square =& $this->square[$king->x][$king->y];
$this->updateData();
foreach ($king_square->controlled_by as $piece)
{
if ($piece->color != $king->color)
{
$this->is_check = true;
break;
}
}
foreach ($king->controlled_squares as $move)
{
if ($king->validateMove($this, $move{0}, $move{1}))
{
if ($this->movePiece($king->x, $king->y, $move{0}, $move{1}, false))
{
return false;
}
}
}
for ($x = 1; $x <= 8; $x++)
{
for ($y = 1; $y <= 8; $y++)
{
$square =& $this->square[$x][$y];
$piece =& $square->piece;
if (!$square->hasPiece() || ($piece->color != $king->color) || $piece->isKing())
{
continue;
}
foreach ($piece->controlled_squares as $move)
{
$x_start = $piece->x;
$y_start = $piece->y;
$x_end = $move{0};
$y_end = $move{1};
if ($this->movePiece($x_start, $y_start, $x_end, $y_end, false))
{
return false;
}
}
}
}
if ($this->is_check)
{
$this->is_check_mate = true;
return true;
}
else
{
$this->is_draw = true;
return false;
}
}
function addKing($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_King($color, $x, $y, $num_moves));
}
function addQueen($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_Queen($color, $x, $y, $num_moves));
}
function addBishop($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_Bishop($color, $x, $y, $num_moves));
}
function addKnight($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_Knight($color, $x, $y, $num_moves));
}
function addRook($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_Rook($color, $x, $y, $num_moves));
}
function addPawn($color, $x, $y, $num_moves = 0)
{
$this->square[$x][$y]->piece =& $this->$color->addPiece(new PHPChess_Pawn($color, $x, $y, $num_moves));
}
// Updates all relevant data for each move (sets all the squares controlled by the opponent)
function updateData()
{
$opponent_color = $this->turn(false);
for ($x = 1; $x <= 8; $x++)
{
for ($y = 1; $y <= 8; $y++)
{
$this->square[$x][$y]->controlled_by = array();
}
}
for ($x = 1; $x <= 8; $x++)
{
for ($y = 1; $y <= 8; $y++)
{
$square =& $this->square[$x][$y];
if ($square->hasPiece() && ($square->piece->color == $opponent_color))
{
$square->piece->getControlledSquares($this);
}
}
}
}
function packData()
{
$packed_data = array(
'history' => implode("-", $this->history),
'white' => $this->white->email,
'black' => $this->black->email,
);
return urlencode(serialize($packed_data));
}
function unpackData($packed_data)
{
if (!is_string($packed_data))
{
return false;
}
$data = unserialize(stripslashes($packed_data));
$this->white->email = $data['white'];
$this->black->email = $data['black'];
$history = explode("-", $data['history']);
foreach ($history as $i => $move)
{
if (!preg_match("/^[1-8]{4}$/", $move))
{
continue;
}
$this->movePiece($move{0}, $move{1}, $move{2}, $move{3});
}
$this->user =& $this->{$this->turn(true)};
$this->opponent =& $this->{$this->turn(false)};
$this->verifyCheckMate();
return true;
}
}
class PHPChess_Player
{
var $color; // (string) Pieces color
var $pieces; // (array) Array of objects. Each element is a piece of this player
var $email; // (string) Player's e-mail
function PHPChess_Player($color, $email = "")
{
$this->color = (string)$color;
$this->pieces = array();
$this->email = (string)$email;
}
function addPiece($piece)
{
if ($piece->isKing())
{
return $this->pieces['king'] = $piece;
}
else
{
return $this->pieces[] = $piece;
}
}
function setEmail($email)
{
$this->email = (string)$email;
}
}
class PHPChess_Square
{
var $x; // (int) Square X coordinate
var $y; // (int) Square Y coordinate
var $piece; // (mixed) Will be "false" if the square is empty, or object if it has a piece
var $controlled_by; // (array) Array with the opponent's pieces that control this square
function PHPChess_Square($x, $y)
{
$this->x = (int)$x;
$this->y = (int)$y;
$this->piece = false;
$this->controlled_by = array();
}
function hasPiece()
{
return (bool)$this->piece;
}
}
class PHPChess_Piece
{
var $color; // (string)
var $name; // (string)
var $x; // (int)
var $y; // (int)
var $num_moves; // (int)
var $controlled_squares; // (array) Squares this piece may walk to
function PHPChess_Piece($color, $x, $y, $num_moves = 0)
{
$this->color = (string)$color;
$this->name = "";
$this->x = (int)$x;
$this->y = (int)$y;
$this->num_moves = (int)$num_moves;
$this->controlled_squares = array();
}
function getName()
{
return strtolower(preg_replace("/^PHPChess_/i", "", get_class($this)));
}
function isKing()
{
return preg_match("/king/i", get_class($this));
}
function isQueen()
{
return preg_match("/queen/i", get_class($this));
}
function isBishop()
{
return preg_match("/bishop/i", get_class($this));
}
function isKnight()
{
return preg_match("/knight/i", get_class($this));
}
function isRook()
{
return preg_match("/rook/i", get_class($this));
}
function isPawn()
{
return preg_match("/pawn/i", get_class($this));
}
}
class PHPChess_King extends PHPChess_Piece
{
function PHPChess_King($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
// Controlled squares are those controlled by this piece for this or the next turn. They could be blank
// squares, a square with an opponent's piece on it, or even a square with a piece of the same color
// (because if the piece is captured, that square will be controlled on the next turn).
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
if ($x_variation == 0)
{
if ($y_variation != 1)
{
return false;
}
}
else if ($x_variation == 1)
{
if (($y_variation != 0) && ($y_variation != 1))
{
return false;
}
}
// Castling
else if (($x_variation == 2) && ($this->num_moves == 0))
{
if ($y_variation != 0)
{
return false;
}
if ($x < $this->x)
{
// If King walked to "A" file, checks if the square beside the Rook is vacant
if ($board->square[2][$this->y]->hasPiece())
{
return false;
}
$rook =& $board->square[1][$this->y]->piece;
$_x = -1;
}
else
{
$rook =& $board->square[8][$this->y]->piece;
$_x = +1;
}
// Checks if rook has not moved yet
if ($rook && $rook->isRook() && ($rook->num_moves == 0))
{
// Checks if king is not under attack
foreach ($board->square[$this->x][$this->y]->controlled_by as $p)
{
if ($p->color != $this->color)
{
return false;
}
}
// Checks if all of the squares between the king and rook are vacant
// Checks if king is not passing through or arriving upon a square controlled by the opponent
for ($i = 1; $i <= 2; $i++)
{
$square =& $board->square[ ($this->x + ($i * $_x)) ][$this->y];
if ($square->hasPiece())
{
return false;
}
foreach ($square->controlled_by as $p)
{
if ($p->color != $this->color)
{
return false;
}
}
}
return true;
}
return false;
}
else
{
// $x_variation is not 0, 1 or 2
return false;
}
$square =& $board->square[$x][$y];
if (($this->color != $board->turn()) || (count($square->controlled_by) == 0))
{
if (!$square->hasPiece() || ($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
for ($x = ($this->x - 1); $x <= ($this->x + 1); $x++)
{
for ($y = ($this->y - 1); $y <= ($this->y + 1); $y++)
{
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
}
}
}
if ($this->num_moves == 0)
{
for ($x = ($this->x - 2); $x <= ($this->x + 2); $x += 4)
{
if ($this->validateMove($board, $x, $this->y, $piece_turn))
{
$this->controlled_squares[] = $x . $this->y;
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Queen extends PHPChess_Piece
{
function PHPChess_Queen($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
if (($x_variation == 0) && ($y_variation == 0))
{
return false;
}
else if (($x_variation != 0) && ($y_variation != 0))
{
if ($x_variation != $y_variation)
{
return false;
}
}
$_x = ($x < $this->x) ? -1 : (($x > $this->x) ? +1 : 0);
$_y = ($y < $this->y) ? -1 : (($y > $this->y) ? +1 : 0);
$i = $this->x + $_x;
$j = $this->y + $_y;
while (($i != $x) || ($j != $y))
{
if ($board->square[$i][$j]->hasPiece())
{
return false;
}
$i += $_x;
$j += $_y;
}
$square =& $board->square[$x][$y];
if (!$square->hasPiece() || ($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
$x_directions = $y_directions = array(-1, 0, 1);
foreach ($x_directions as $_x)
{
foreach ($y_directions as $_y)
{
if (($_x == 0) && ($_y == 0))
{
continue;
}
$x = $this->x + $_x;
$y = $this->y + $_y;
while ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
$x += $_x;
$y += $_y;
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Bishop extends PHPChess_Piece
{
function PHPChess_Bishop($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
if (($x_variation == 0) || ($y_variation == 0) || ($x_variation != $y_variation))
{
return false;
}
$_x = ($x < $this->x) ? -1 : +1;
$_y = ($y < $this->y) ? -1 : +1;
$i = $this->x + $_x;
$j = $this->y + $_y;
while (($i != $x) || ($j != $y))
{
if ($board->square[$i][$j]->hasPiece())
{
return false;
}
$i += $_x;
$j += $_y;
}
$square =& $board->square[$x][$y];
if (!$square->hasPiece() || ($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
$x_directions = $y_directions = array(-1, 1);
foreach ($x_directions as $_x)
{
foreach ($y_directions as $_y)
{
$x = $this->x + $_x;
$y = $this->y + $_y;
while ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
$x += $_x;
$y += $_y;
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Knight extends PHPChess_Piece
{
function PHPChess_Knight($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
if ( !((($x_variation == 1) && ($y_variation == 2)) || (($x_variation == 2) && ($y_variation == 1))) )
{
return false;
}
$square =& $board->square[$x][$y];
if (!$square->hasPiece() || ($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
$x_positions = $y_positions = array(-2, -1, 1, 2);
foreach ($x_positions as $_x)
{
foreach ($y_positions as $_y)
{
if (abs($_x) == abs($_y))
{
continue;
}
$x = $this->x + $_x;
$y = $this->y + $_y;
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Rook extends PHPChess_Piece
{
function PHPChess_Rook($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
if (!(($x_variation == 0) ^ ($y_variation == 0)))
{
return false;
}
$_x = ($x < $this->x) ? -1 : (($x > $this->x) ? +1 : 0);
$_y = ($y < $this->y) ? -1 : (($y > $this->y) ? +1 : 0);
$i = $this->x + $_x;
$j = $this->y + $_y;
while (($i != $x) || ($j != $y))
{
if ($board->square[$i][$j]->hasPiece())
{
return false;
}
$i += $_x;
$j += $_y;
}
$square =& $board->square[$x][$y];
if (!$square->hasPiece() || ($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
$x_directions = $y_directions = array(-1, 0, 1);
foreach ($x_directions as $_x)
{
foreach ($y_directions as $_y)
{
if (!(($_x == 0) ^ ($_y == 0)))
{
continue;
}
$x = $this->x + $_x;
$y = $this->y + $_y;
while ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
$x += $_x;
$y += $_y;
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Pawn extends PHPChess_Piece
{
function PHPChess_Pawn($color, $x, $y)
{
parent::PHPChess_Piece($color, $x, $y);
}
function validateMove(&$board, $x, $y, $piece_turn = true)
{
if (($x < 1) || ($x > 8) || ($y < 1) || ($y > 8))
{
return false;
}
else if (($this->y < $y) && ($this->color != "white") || ($this->y > $y) && ($this->color != "black"))
{
return false;
}
$x_variation = abs($this->x - $x);
$y_variation = abs($this->y - $y);
$_y = ($this->color == "white") ? +1 : -1;
if ($x_variation == 0)
{
$i = $this->x;
$j = $this->y + $_y;
$square =& $board->square[$i][$j];
if (!$square->hasPiece())
{
if ($y_variation == 1)
{
return true;
}
else if (($y_variation == 2) && ($this->num_moves == 0))
{
$j += $_y;
$square =& $board->square[$i][$j];
if (!$square->hasPiece())
{
return true;
}
}
}
}
else if ($x_variation == 1)
{
if ($y_variation == 1)
{
$square =& $board->square[$x][$y];
if ($square->hasPiece())
{
if (($square->piece->color != $this->color) || !$piece_turn)
{
return true;
}
}
// "En passant" (capture while passing)
else
{
$square =& $board->square[$x][$this->y];
if ($square->hasPiece() && $square->piece->isPawn() && ($square->piece->color != $this->color))
{
$move = end($board->history);
$pawn =& $square->piece;
if (($pawn->num_moves == 1) && ($pawn->x == $move{2}) && ($pawn->y == $move{3}))
{
return true;
}
}
}
}
}
return false;
}
function getControlledSquares(&$board)
{
$this->controlled_squares = array();
$piece_turn = ($this->color == $board->turn());
$_y = ($this->color == "white") ? +1 : -1;
for ($x = ($this->x - 1); $x <= ($this->x + 1); $x += 2)
{
$y = $this->y;
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
}
$y = $this->y + $_y;
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if (!$piece_turn)
{
$board->square[$x][$y]->controlled_by[] =& $this;
}
}
}
$x = $this->x;
$y = $this->y + $_y;
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
if ($this->num_moves == 0)
{
$y += $_y;
if ($this->validateMove($board, $x, $y, $piece_turn))
{
$this->controlled_squares[] = $x . $y;
}
}
}
return $this->controlled_squares;
}
}
class PHPChess_Interface
{
var $board; // (object) An alias to "PHPChess::board" property
var $script_file; // (string)
var $javascript_loaded; // (bool)
var $smtp_server; // (string)
var $message; // (string)
var $image_dir; // (string)
var $square_size; // (int)
var $show_coordinates; // (bool)
function PHPChess_Interface(&$board)
{
if (!is_object($board))
{
$this->error("Wrong parameters for "PHPChess::interface" property!");
return false;
}
$this->board =& $board;
$this->javascript_loaded = false;
$htis->smtp_server = "";
$this->message = "";
$this->script_file = (isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] :
(isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : "#"));
$this->image_dir = "";
$this->square_size = 35;
$this->show_coordinates = false;
}
// Email users
function emailPlayers()
{
if ($this->smtp_server != "")
{
@ini_set("SMTP", $this->smtp_server);
}
$sent = true;
if (!isset($_SERVER['HTTP_HOST']) || ($this->script_file == "#"))
{
$this->error("Internal server error! PHP Chess could not send an e-mail with the link to access the board.");
return false;
}
if (isset($_SERVER['SERVER_PROTOCOL']))
{
$scheme = explode("/", strtolower($_SERVER['SERVER_PROTOCOL']));
$link = $scheme[0] . "://" . $_SERVER['HTTP_HOST'];
}
else
{
$link = "http://" . $_SERVER['HTTP_HOST'];
}
$link .= (!preg_match("/^\\//s", $this->script_file)) ? "/" : "";
$link .= $this->script_file . "?game_data=" . $this->board->packData();
// Email opponent
$headers = "From: # PHP Chess <" . $this->board->user->email . ">\r\n";
$headers .= "Reply-To: " . $this->board->user->email . "\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
if (count($this->board->history) == 1)
{
$subject = $this->board->user->email . " has invited you to start a new chess game!";
$message = "PHP Chess 1.0\n==================================================\n\n";
$message .= "Your friend at " . $this->board->user->email . " has invited you to start a new ";
$message .= "chess game! Click on the link\n" . $link . "\nto go to the board and move your piece.\n\n";
$message .= (!empty($_POST['message'])) ? ("Opponent's message:\n\"".$_POST['message']."\"\n\n") : "";
$message .= "__________________________________________________\nPHP Chess by Carlos Reche\n";
}
else
{
$authentication_code = $this->authenticationCode($this->board->opponent->color);
$subject = "Your opponent has moved! Authentication #" . $authentication_code;
$message = "PHP Chess 1.0\n==================================================\n\n";
$message .= "Your opponent has moved! Click on the link\n" . $link . "\nto go to the board ";
$message .= "and move your piece.\n\n";
$message .= (!empty($_POST['message'])) ? ("Opponent's message:\n\"".$_POST['message']."\"\n\n") : "";
$message .= "Authentication code: #" . $authentication_code;
$message .= "\n\n__________________________________________________\nPHP Chess by Carlos Reche\n";
}
if(!@mail($this->board->opponent->email, $subject, $message, $headers))
{
$this->error("Could NOT email your opponent!");
$sent = false;
}
// Email user
$authentication_code = $this->authenticationCode($this->board->user->color);
$headers = "From: # PHP Chess <" . $this->board->opponent->email . ">\r\n";
$headers .= "Reply-To: hide@address.com\r\n";
$headers .= "X-Mailer: PHP/" . phpversion();
$subject = "Next authentication should be #" . $authentication_code;
$message = "PHP Chess 1.0\n==================================================\n\n";
$message .= "Your move was sent to " . $this->board->opponent->email . "\n\n";
$message .= (!empty($_POST['message'])) ? ("Message:\n\"" . $_POST['message'] . "\"\n\n") : "";
$message .= "Authentication code: #" . $authentication_code . "\n\n";
$message .= "PHP Chess generates an authentication code on each move. When you receive the response from your ";
$message .= "opponent, this code will assure you that it has been made right after the move sent now.";
$message .= "\n\n__________________________________________________\nPHP Chess by Carlos Reche\n";
if(!@mail($this->board->user->email, $subject, $message, $headers))
{
$this->error("Could NOT send you a confirmation email!");
$sent = false;
}
/* Helps when debugging
if (!$this->board->is_check_mate)
{
echo '<a href="' . $link . '"> NEXT >> </a>';
}
*/
return $sent;
}
function board($bool_return = false)
{
if ($this->board->user->color == "white")
{
$x_start = 1;
$x_increment = +1;
$y_start = 8;
$y_increment = -1;
}
else
{
$x_start = 8;
$x_increment = -1;
$y_start = 1;
$y_increment = +1;
}
$table_style = "margin: 0px auto; text-align: center; cursor: default; ";
$table_style .= " border: " . floor($this->square_size / 7) . "px double #a6735b;";
$table_style .= " font-family: Bookman Old Style, Arial Unicode MS; font-size: " . floor($this->square_size * 5 / 7) . "px;";
$html_board = "\n".'<table cellspacing="0" cellpadding="0" style="' . $table_style . '" id="board">';
for ($y = $y_start; (($y-1 & 8) == 0); $y += $y_increment)
{
$html_board .= "\n".' <tr>';
for ($x = $x_start; (($x-1 & 8) == 0); $x += $x_increment)
{
if ((($x % 2) == 0) ? ((($y % 2) == 1) ? true : false) : ((($y % 2) == 1) ? false : true))
{
$class = "light";
$color = "#e7d0a7";
}
else
{
$class = "dark";
$color = "#a6735b";
}
$square =& $this->board->square[$x][$y];
$piece =& $square->piece;
$events = ' onmouseover="javascript: highlightSquare('.$x.', '.$y.', true);"';
$events .= ' onmouseout="javascript: highlightSquare('.$x.', '.$y.', false);"';
$events .= ' onclick="javascript: selectSquare('.$x.', '.$y.');"';
if ($square->hasPiece())
{
$square_contents = $this->printPiece($piece);
}
else
{
$square_contents = '<div style="width: ' . $this->square_size . 'px;';
$square_contents .= ' height: ' . $this->square_size . 'px;"></div>';
}
$html_board .= "\n".' <td id="square_' . ($x.$y) . '"' . $events;
$html_board .= ' style="width: ' . $this->square_size . 'px; height: ' . $this->square_size . 'px;';
$html_board .= ' vertical-align: middle; border: 1px solid ' . $color . '; background-color: ' . $color.';"';
$html_board .= ' class="' . $class . '">';
$html_board .= "\n".' ' . $square_contents;
$html_board .= "\n".' </td>';
}
$html_board .= "\n".' </tr>';
}
$html_board .= "\n".'</table>';
$html_board .= "\n\n".'<script type="text/javascript">';
if (!empty($_POST['mov_start']))
{
$html_board .= "\n selectSquare(".$this->valueOfX($_POST['mov_start']{0}).", ".$_POST['mov_start']{1}.");";
}
if (!empty($_POST['mov_end']))
{
$html_board .= "\n selectSquare(".$this->valueOfX($_POST['mov_end']{0}).", ".$_POST['mov_end']{1}.");";
}
$html_board .= "\n</script>\n\n";
$html = $this->loadJavaScript(true);
if (!$this->show_coordinates)
{
return $this->printHTML(($html . $html_board), $bool_return);
}
// Outer table (with board coordinates)
$html .= "\n".'<table style="margin: 0px auto; text-align: center; font-family: Tahoma, Arial;';
$html .= ' font-size: 11px; font-weight: bold; color: #777;"';
$html .= ' cellspacing="0" cellpadding="0">';
for ($y = $y_start; (($y-1 & 8) == 0); $y += $y_increment)
{
$html .= "\n".' <tr><td style="height: ' . $this->square_size . 'px;';
$html .= ' padding-right: 7px; vertical-align: middle;">' . $y . '</td>';
if ($y == $y_start)
{
$html .= '<td colspan="8" rowspan="8">' . $html_board . '</td>';
}
$html .= '</tr>';
}
$html .= "\n".' <tr><td> </td>';
for ($x = $x_start; (($x-1 & 8) == 0); $x += $x_increment)
{
$html .= '<td style="width: ' . $this->square_size . 'px; padding-top: 2px;">' . $this->valueOfX($x) . '</td>';
}
$html .= "\n".' </tr>';
$html .= "\n".'</table>';
return $this->printHTML($html, $bool_return);
}
function form($bool_return = false)
{
$qs = array();
foreach ($_GET as $var => $value)
{
$qs[] = $var . "=" . urlencode($value);
}
$query_string = (count($qs) > 0) ? ("?" . implode("&", $qs)) : "";
$disabled = "";
$html = "";
if ($this->board->has_moved)
{
$message = "Could not send emails!";
if ($this->emailPlayers())
{
$message = 'Move sent!';
$disabled = ' disabled="disabled"';
}
$html .= '<script type="text/javascript">alert("' . $message . '");</script>';
}
$html .= $this->loadJavaScript(true);
$html .= "\n".'<form action="' . $this->script_file . $query_string . '" method="post" id="phpchess_form"';
$html .= ' style="margin: 20px 0px;" onsubmit="javascript: return validateForm();">';
$html .= "\n".' <table border="0" id="form_table" cellspacing="0" cellpadding="3" style="margin: 0px auto;">';
$html .= "\n".' <tr>';
$html .= "\n".' <td colspan="2" style="text-align: center;">';
$html .= "\n".' <input type="hidden" name="mov_start" id="mov_start"';
$html .= ' value="' . (!empty($_POST['mov_start']) ? $_POST['mov_start'] : "") . '" />';
$html .= "\n".' <input type="hidden" name="mov_end" id="mov_end"';
$html .= ' value="' . (!empty($_POST['mov_end']) ? $_POST['mov_end'] : "") . '" />';
$html .= "\n".' <input type="submit" id="submit_button" value="Move"' . $disabled;
$html .= ' style="margin-bottom: 20px; width: 250px; height: 30px;" />';
$html .= "\n".' </td>';
$html .= "\n".' </tr>';
$html .= "\n".' <tr>';
$html .= "\n".' <td>Your e-mail:</td>';
$html .= "\n".' <td><input type="text" name="' . $this->board->user->color . '"';
$html .= ' id="' . $this->board->user->color . '" value="' . $this->board->user->email . '"';
$html .= "\n". ' style="width: 100%;"' . $disabled . ' /></td>';
$html .= "\n".' </tr>';
$html .= "\n".' <tr>';
$html .= "\n".' <td>Opponent\'s e-mail:</td>';
$html .= "\n".' <td><input type="text" name="' . $this->board->opponent->color . '"';
$html .= ' id="' . $this->board->opponent->color . '" value="' . $this->board->opponent->email . '"';
$html .= "\n". ' style="width: 100%;"' . $disabled . ' /></td>';
$html .= "\n".' </tr>';
$html .= "\n".' <tr>';
$html .= "\n".' <td style="vertical-align: top;">Message:<br /><em>(Optional)</em></td>';
$html .= "\n".' <td>';
$html .= "\n".' <textarea name="message" id="message" style="vertical-align: top;"' . $disabled . '>';
$html .= (isset($_POST['message']) ? $_POST['message'] : "") . '</textarea>';
$html .= "\n".' </td>';
$html .= "\n".' </tr>';
$html .= "\n".' </table>';
$html .= "\n".'</form>';
return $this->printHTML($html, $bool_return);
}
function loadJavaScript($bool_return = false)
{
if ($this->javascript_loaded)
{
return false;
}
$this->javascript_loaded = true;
$html = '
<script type="text/javascript">
/*
* Custom object types
*/
function PHPChess_Board()
{
this.turn = "' . $this->board->turn() . '";
this.square = new Array(8);
this.form = new PHPChess_Form();
this.move = new PHPChess_Move();
this.show = _PHPChess_Show;
this.valueOfX = _PHPChess_Board_valueOfX;
for (x = 1; x <= 8; x++)
{
this.square[x] = new Array(8);
for (y = 1; y <= 8; y++)
{
this.square[x][y] = new PHPChess_Square(x, y);
}
}
}
function _PHPChess_Show(piece_color, piece_name)
{
var isIE = (navigator.appName.match(/Internet\s+Explorer/i));
var text = "", color = ((piece_color == "white") ? "#ffd" : "#633"), html = "";
switch (piece_name)
{
// Internet Explorer does not support the Unicode Characters of the pieces
case "king": (text = !isIE ? "♚" : "Θ"); break;
case "queen": (text = !isIE ? "♛" : "Փ"); break;
case "bishop": (text = !isIE ? "♝" : "Ճ"); break;
case "knight": (text = !isIE ? "♞" : "Ջ"); break;
case "rook": (text = !isIE ? "♜" : "□"); break;
case "pawn": (text = !isIE ? "♟" : "∆"); break;
}
html = "<span style=\"color: " + color + ";\" class=\"" + piece_color + "_piece\">" + text + "</span>";
document.write(html);
}
function _PHPChess_Board_valueOfX(value)
{
value = new String(value);
if (value.match(/^[1-8]$/))
{
return String.fromCharCode(64 + parseInt(value));
}
else if (value.match(/^[A-H]$/i))
{
value = value.toUpperCase();
return (parseInt(value.charCodeAt(0)) - 64);
}
else
{
return false;
}
}
function PHPChess_Square(x, y)
{
this.x = x;
this.y = y;
this.piece = null;
}
function PHPChess_Piece(x, y, color, controlled_squares)
{
this.x = x;
this.y = y;
this.color = color;
this.controlled_squares = controlled_squares;
}
function PHPChess_Move()
{
this.start = false;
this.end = false;
this.removed = "";
this.go = _PHPChess_Move_go;
this.undo = _PHPChess_Move_undo;
}
function _PHPChess_Move_go()
{
start_square = document.getElementById("square_" + this.start.charAt(0) + this.start.charAt(1));
end_square = document.getElementById("square_" + this.end.charAt(0) + this.end.charAt(1));
this.removed = end_square.innerHTML;
end_square.innerHTML = start_square.innerHTML;
start_square.innerHTML = " ";
}
function _PHPChess_Move_undo()
{
if (this.removed == "")
{
return false;
}
start_square = document.getElementById("square_" + this.start.charAt(0) + this.start.charAt(1));
end_square = document.getElementById("square_" + this.end.charAt(0) + this.end.charAt(1));
start_square.innerHTML = end_square.innerHTML;
end_square.innerHTML = this.removed;
this.removed = "";
this.start = false;
this.end = false;
}
function PHPChess_Form()
{
this.setStart = _PHPChess_Form_setStart;
this.setEnd = _PHPChess_Form_setEnd;
this.unsetStart = _PHPChess_Form_unsetStart;
this.unsetEnd = _PHPChess_Form_unsetEnd;
}
function _PHPChess_Form_setStart()
{
value = Board.valueOfX(Board.move.start.charAt(0)) + String(Board.move.start.charAt(1));
document.getElementById("mov_start").value = value;
}
function _PHPChess_Form_setEnd()
{
value = Board.valueOfX(Board.move.end.charAt(0)) + String(Board.move.end.charAt(1));
document.getElementById("mov_end").value = value;
}
function _PHPChess_Form_unsetStart()
{
document.getElementById("mov_start").value = "";
}
function _PHPChess_Form_unsetEnd()
{
document.getElementById("mov_end").value = "";
}
/*
* Custom functions
*/
function highlightSquare(x, y, highlight)
{
if (highlight == null)
{
highlight = true;
}
if (Board.move.end)
{
return false;
}
else if (Board.move.start)
{
x_start = Board.move.start.charAt(0);
y_start = Board.move.start.charAt(1);
controlled_squares = Board.square[x_start][y_start].piece.controlled_squares.toString();
if (!controlled_squares.match( eval("/" + String(x) + String(y) + "/") ))
{
return false;
}
}
else
{
piece = Board.square[x][y].piece;
if ((piece == null) || (piece.color != Board.turn) || (piece.controlled_squares.length == 0))
{
return false;
}
}
objStyle = document.getElementById(("square_" + x) + y).style;
objStyle.border = ((highlight) ? "1px solid #00f" : "");
objStyle.cursor = "pointer";
}
function selectSquare(x, y)
{
var coordinate = String(x) + String(y);
if (Board.move.end)
{
if ((coordinate != Board.move.start) && (coordinate != Board.move.end))
{
x_start = Board.move.start.charAt(0);
y_start = Board.move.start.charAt(1);
x_end = Board.move.end.charAt(0);
y_end = Board.move.end.charAt(1);
document.getElementById("square_" + String(x_start) + String(y_start)).style.border = "";
document.getElementById("square_" + String(x_end) + String(y_end)).style.border = "";
Board.move.undo();
Board.form.unsetStart();
Board.form.unsetEnd();
}
return true;
}
else if (Board.move.start)
{
x_start = Board.move.start.charAt(0);
y_start = Board.move.start.charAt(1);
controlled_squares = Board.square[x_start][y_start].piece.controlled_squares.toString();
if (!controlled_squares.match( eval("/" + coordinate + "/") ))
{
document.getElementById("square_" + String(x_start) + String(y_start)).style.border = "";
Board.move.start = false;
Board.form.unsetStart();
return false;
}
document.getElementById("square_" + coordinate).style.border = "1px solid #f00";
Board.move.end = coordinate;
Board.move.go();
Board.form.setEnd();
return true;
}
piece = Board.square[x][y].piece;
if ((piece == null) || (piece.color != Board.turn) || (piece.controlled_squares.length == 0))
{
return false;
}
document.getElementById("square_" + coordinate).style.border = "1px solid #f00";
Board.move.start = coordinate;
Board.form.setStart();
return true;
}
function validateForm()
{
var mov_start = document.getElementById("mov_start").value;
var mov_end = document.getElementById("mov_end").value;
var email_white = document.getElementById("white");
var email_black = document.getElementById("black");
if ((mov_start == "") || (mov_end == ""))
{
alert("Move a piece on the board first!");
return false;
}
else if (email_white.value.replace(/^\s+/, "").replace(/\s+$/, "") == "")
{
who = (Board.turn != "white") ? " opponent\'s" : "";
alert("Type your" + who + " email!");
email_white.value = "";
email_white.focus();
return false;
}
else if (email_black.value.replace(/^\s+/, "").replace(/\s+$/, "") == "")
{
who = (Board.turn != "black") ? " opponent\'s" : "";
alert("Type your" + who + " email!");
email_black.value = "";
email_black.focus();
return false;
}
return true;
}
/*
* Starts main object
*/
Board = new PHPChess_Board();
';
if (!$this->board->has_moved && !$this->board->is_check_mate && !$this->board->is_stalemate)
{
$this->board->updateData();
for ($x = 1; $x <= 8; $x++)
{
for ($y = 1; $y <= 8; $y++)
{
if (!$this->board->square[$x][$y]->hasPiece())
{
continue;
}
$piece =& $this->board->square[$x][$y]->piece;
$controlled_squares = $piece->getControlledSquares($this->board);
$parameters = $piece->x . ', ' . $piece->y . ', "' . $piece->color . '", new Array()';
$html .= "\n".' Board.square[' . $x . '][' . $y . '].piece = new PHPChess_Piece(' . $parameters . ');';
if (count($controlled_squares) > 0)
{
$html .= "\n".' Board.square[' . $x . '][' . $y . '].piece.controlled_squares';
$html .= '.push(' . implode(", ", $controlled_squares) . ');';
}
}
}
}
$html .= "\n\n</script>";
return $this->printHTML($html, $bool_return);
}
function message($bool_return = false)
{
if (($this->message == "") && (count($this->board->history) > 0))
{
$move = end($this->board->history);
$x_start = $move{0};
$y_start = $move{1};
$x_end = $move{2};
$y_end = $move{3};
$coordinate = $this->valueOfX($x_start) . $y_start . $this->valueOfX($x_end) . $y_end;
$piece_mov =& $this->board->square[$x_end][$y_end]->piece;
$piece_cap =& $this->board->removed_piece;
$piece_mov_name = $piece_mov->color . ' ' . $piece_mov->getName();
if ($piece_mov->isKing() && (abs($x_start - $x_end) == 2))
{
$this->message = 'Castled ' . $piece_mov_name . ' at ' . $coordinate . '.';
}
else if (!$piece_cap)
{
$this->message = 'Moved ' . $piece_mov->color . ' ' . $piece_mov->getName() . ' at ' . $coordinate . '.';
}
else
{
$en_passant = "";
if ($piece_mov->isPawn() && (abs($x_start - $x_end) == 1) && ($piece_mov->y != $piece_cap->y))
{
$en_passant = " "en passant" ";
}
$this->message = ucfirst($piece_mov_name) . ' captures ';
$this->message .= $piece_cap->color . ' ' . $piece_cap->getName() . $en_passant . ' at ' . $coordinate . '.';
}
if ($this->board->is_check)
{
if ($this->board->is_check_mate)
{
$this->message .= ' <strong>Checkmate! ' . ucfirst($piece_mov->color) . ' wins.</strong>';
}
else
{
$this->message .= ' <strong>Check!</strong>';
}
}
else if ($this->board->is_draw)
{
$this->message .= ' <strong>Stalemate!</strong>';
}
}
return $this->printHTML('<span id="message">' . $this->message . '</span>', $bool_return);
}
function setMessage($message)
{
$this->message = (string)$message;
}
function authenticationCode($color)
{
$history = $this->board->history;
if ($color != $this->board->user->color)
{
array_pop($history);
}
$hash = md5(implode("", $history));
for ($code = "", $i = 0; $i < 32; $i += 7)
{
$code .= $hash{$i};
}
return strtoupper($code);
}
function valueOfX($value)
{
if (preg_match("/^[1-8]$/", $value))
{
return chr(64 + (int)$value);
}
else if (preg_match("/^[A-H]$/i", $value))
{
return (ord(strtoupper($value)) - 64);
}
else
{
return false;
}
}
function printPiece($piece)
{
if (!is_object($piece))
{
return false;
}
$piece_file = $this->image_dir . $piece->color . '_' . $piece->getName() . '.gif';
if (is_file($piece_file))
{
$html = '<img src="' . $piece_file . '" alt="" class="' . $piece->color . '_piece" />';
}
else
{
$html = '<script type="text/javascript">Board.show("' . $piece->color . '", "' . $piece->getName() . '");</script>';
}
return $html;
}
function printHTML($html, $bool_return = false)
{
if ($bool_return)
{
return $html;
}
else
{
echo $html;
return true;
}
}
function setSMTP($smtp)
{
$this->smtp_server = (string)$smtp;
}
function error($message = "")
{
$message = ($message != "") ? (" ".$message) : "";
echo "\n<p>\n ";
echo '<span style="padding: 1px 7px; background-color: #ffd7d7; font-family: Verdana;';
echo ' font-weight: normal; color: #000; font-size: 13px;">';
echo '<span style="color: #f00; font-weight: bold;">Error!</span>' . $message . '</span>';
echo "\n</p>\n";
}
}
?>