exec("DELETE FROM BoardState WHERE SessionID = '". session_id() . "'"); //Create new empty BoardState $statement = $database->prepare('INSERT INTO BoardState(SessionID, access) VALUES (:sessionid, :timestamp)'); $statement->bindValue(':sessionid', session_id()); $statement->bindValue(':timestamp', time()); $result = $statement->execute(); $BoardState = array( "B1"=> NULL, "B2"=> NULL, "B3"=> NULL, "B4"=> NULL, "B5"=> NULL, "B6"=> NULL, "B7"=> NULL, "B8"=> NULL, "B9"=> NULL, "W1"=> NULL, "W2"=> NULL, "W3"=> NULL, "W4"=> NULL, "W5"=> NULL, "W6"=> NULL, "W7"=> NULL, "W8"=> NULL, "W9"=> NULL ); unset ($_SESSION['currPlayerMoveFrom']); unset ($_SESSION['currComputerMoveFrom']); unset ($_SESSION['currPlayerMoveTo']); unset ($_SESSION['currComputerMoveTo']); unset ($_SESSION["winner"]); unset ($_SESSION['playerMill']); unset ($_SESSION['computerMill']); $_SESSION["SetupStage"] = 1; } function ContinueGame() { global $BoardState, $database; //fetch board state $statement = $database->prepare('SELECT B1, B2, B3, B4, B5, B6, B7, B8, B9, W1, W2, W3, W4, W5, W6, W7, W8, W9 FROM BoardState WHERE SessionID = :sessionid'); $statement->bindValue(':sessionid', session_id()); $result = $statement->execute(); if (!$result) die($databse->lastErrorMsg()); $BoardState = $result->fetchArray(SQLITE3_ASSOC); // If no board state exists for this session then create a new board state. if ($BoardState == NULL) StartNewGame(); } function isSetupStage() { return (isset($_SESSION["SetupStage"]) && filter_var($_SESSION["SetupStage"], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 9)))); } function getPieceColour($nodeID) { global $BoardState; $pieceID = array_search($nodeID, $BoardState); if ($pieceID) return ($pieceID[0] == 'B')? "black" : "white"; else return "vacant"; } function MovePieceToPos($pieceID, $positionID) { global $BoardState, $database; $statement = $database->prepare("UPDATE BoardState SET $pieceID = :positionID, access = :timestamp WHERE SessionID = :sessionid"); $statement->bindValue(':positionID', $positionID); $statement->bindValue(':timestamp', time()); $statement->bindValue(':sessionid', session_id()); $result = $statement->execute(); if ($result) { $BoardState[$pieceID] = $positionID; } else { echo $databse->lastErrorMsg(); echo "Moving piece: UPDATE BoardState SET $pieceID = $positionID, access = ".time()." WHERE SessionID = ".session_id(). "
"; } } function RemovePiece($pieceID) { global $BoardState, $database; if (!isset($pieceID)) { echo "Remove Piece: pieceID not set"; return; } $statement = $database->prepare("UPDATE BoardState SET $pieceID = -1, access = :timestamp WHERE SessionID = :sessionid"); $statement->bindValue(':timestamp', time()); $statement->bindValue(':sessionid', session_id()); $result = $statement->execute(); if ($result) { $BoardState[$pieceID] = -1; } else { echo "Removing Piece: UPDATE BoardState SET $pieceID = -1, access = ".time()." WHERE SessionID = ".session_id(). "
"; echo $databse->lastErrorMsg(); } } function isValidSetupMove($positionID) { return getPieceColour($positionID) == "vacant"; } function listValidSetupMoves() { $validMoves = array(); for ($pos = 1; $pos <= 24; $pos++) { if (getPieceColour($pos) == "vacant") $validMoves[] = $pos; } return $validMoves; } function isValidMove($fromPosID, $toPosID) { return in_array($toPosID, listValidMoves($fromPosID)); } function listValidMoves($fromPosID) { global $BoardState, $database; $validMoves = array(); if (!isset($fromPosID)) { return $validMoves; } $statement = $database->prepare("SELECT Node2 from NineMensPaths WHERE Node1 = :positionID"); $statement->bindValue(':positionID', $fromPosID); $result = $statement->execute(); if (!$result) die($databse->lastErrorMsg()); while ($row = $result->fetchArray()) { if (getPieceColour($row["Node2"]) == "vacant") $validMoves[] = $row["Node2"]; } return $validMoves; } function countPiecesOnBoard($BW) { global $BoardState; $i = 0; foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL && $posID > 0) $i++; } return $i; } function listPiecesWithValidMoves($BW) { global $BoardState; $results = array(); foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL) { $validMoves = listValidMoves($posID); if (count($validMoves) > 0) $results[] = $pieceID; } } return $results; } function listValidMovesForAllPieces($BW) { global $BoardState; $results = array(); foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL) { $validMoves = listValidMoves($posID); foreach ($validMoves as $move) $results[$pieceID][] = $move; } } return $results; } function listPiecesThatCanMoveHere($BW, $targetPos) { global $BoardState; $results = array(); foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL) { $validMoves = listValidMoves($posID); foreach ($validMoves as $move) if ($move == $targetPos) $results[] = $pieceID; } } return $results; } function hasMadeMill($BW) { //returns a list of places the specified player (B or W) could play on their next move to make a Mill global $BoardState, $database; //Get current player positions as comma separated list $currPieces = "(-1" ; foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL) $currPieces .= ",".$posID; } $currPieces .= ")"; if ($BW == "B") $lastMove = $_SESSION["currPlayerMoveTo"]; else $lastMove = $_SESSION["currComputerMoveTo"]; //Get all mills involving the last piece played $querystring = "SELECT Node1, Node2, Node3 FROM NineMensMills WHERE Node1 = $lastMove AND Node2 IN $currPieces AND Node3 in $currPieces UNION "; $querystring .= "SELECT Node1, Node2, Node3 FROM NineMensMills WHERE Node1 IN $currPieces AND Node2 = $lastMove AND Node3 in $currPieces UNION "; $querystring .= "SELECT Node1, Node2, Node3 FROM NineMensMills WHERE Node1 IN $currPieces AND Node2 in $currPieces AND Node3 = $lastMove"; $result = $database->query($querystring); if (!$result) die($databse->lastErrorMsg()); if ($row = $result->fetchArray(SQLITE3_ASSOC)) { //TO-DO check against previous mills return true; } return false; } function hasLost($BW) { global $debug; $debug .= "checking for $BW loss... "; if (isSetupStage()) return false; $piecesWithMoves = listPiecesWithValidMoves($BW); $countPieces = countPiecesOnBoard($BW); if (!isset($piecesWithMoves) || count($piecesWithMoves) == 0) $debug .= "no moves... "; else $debug .= count($piecesWithMoves)." moves... "; $debug .= $countPieces." pieces... "; if (!isset($piecesWithMoves) || count($piecesWithMoves) == 0 || $countPieces < 3) { $debug .= "LOSS
"; return true; } else { $debug .= "PLAY ON
"; return false; } } function PositionOfPiece($pieceID) { global $BoardState; return $BoardState[$pieceID]; } function PieceAtPosition($posID) { global $BoardState; return array_search($posID, $BoardState); } //function to see if a position can be clicked on by the player function PlayerCanClickHere($posID) { if (isset($_SESSION["winner"])) { return false; } elseif ($_SESSION['playerMill'] == "pending") { if (getPieceColour($posID) == "white") return true; else return false; } elseif (isSetupStage()) { return isValidSetupMove($posID); } elseif (isset($_SESSION['currPlayerMoveFrom']) && !isset($_SESSION['currPlayerMoveTo'])) { $availableMoves = listValidMoves($_SESSION['currPlayerMoveFrom']); return (in_array($posID, $availableMoves)); } elseif (getPieceColour($posID) == "black") { $availableMoves = listValidMoves($posID); return (count($availableMoves) > 0); } else { return false; } } function printArray($array, $sep, $withKeys) { if (!isset($array)) { echo "NULL"; } else { foreach ($array as $key => $value) { if ($withKeys) echo $key ." => "; echo $value . $sep; } } } ?> 0) $chosenMove = $computerPossibleMills[0]; elseif (count($playerPossibleMills) > 0) $chosenMove = $playerPossibleMills[0]; else // if all else fails, pick a random move $chosenMove = $moves[array_rand($moves)]; MovePieceToPos($pieceID, $chosenMove); $_SESSION["currComputerMoveTo"] = $chosenMove; $_SESSION["SetupStage"] ++; } function ComputerStandardMove() { $playerPossibleMills = PlacesCanMill("B"); $computerPossibleMills = PlacesCanMill("W"); //TO-DO - strategy if (count($computerPossibleMills) > 0) { $chosenPiece = array_rand($computerPossibleMills); $i = array_rand($computerPossibleMills[$chosenPiece]); $chosenMove = $computerPossibleMills[$chosenPiece][$i]; } else { // if all else fails, pick a random move $options = listValidMovesForAllPieces("W"); $chosenPiece = array_rand($options); $i = array_rand($options[$chosenPiece]); $chosenMove = $options[$chosenPiece][$i]; } $_SESSION["currComputerMoveFrom"] = PositionOfPiece($chosenPiece); MovePieceToPos($chosenPiece, $chosenMove); $_SESSION["currComputerMoveTo"] = $chosenMove; } function ComputerMillMove() { $possibleMills = AboutToMill("B"); if (isset($possibleMills) && count($possibleMills) > 0) { $i = array_rand($possibleMills); if ($possibleMills[$i]["NextMove"] == $possibleMills[$i]["Node1"]) $pos = $possibleMills[$i]["Node2"]; else $pos = $possibleMills[$i]["Node1"]; $pieceID = PieceAtPosition($pos); } else { // if all else fails, pick a random move $pieceID = randomPiece("B"); $pos = PositionOfPiece($pieceID); } RemovePiece($pieceID); $_SESSION["computerMill"] = $pos; } function randomPiece($BW) { global $BoardState; $currPieces = array(); foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL && $posID != -1) $currPieces[] = $pieceID; } return $currPieces[array_rand($currPieces)]; } function PlacesCanMill($BW) { global $debug; //returns a list of moves (PieceID=>PosID) the Player (black) or Computer (white) could play on their next move to make a Mill $possibleMills = AboutToMill($BW); $debug .= "count(AboutToMill(".$BW.")) = " . count($possibleMills). "
"; $possibleMillMoves = array(); foreach ($possibleMills as $row) { if (isSetupStage()) { $possibleMillMoves[] = $row["NextMove"]; } else { $debug .= "~~~ Possible Mill at ".$row["NextMove"]; $debug .= " (".$row["Node1"].", ".$row["Node2"]. ", ".$row["Node3"]. "), " ; $debug .= count(listPiecesThatCanMoveHere($BW, $row["NextMove"])) . " pieces could move there.
"; foreach(listPiecesThatCanMoveHere($BW, $row["NextMove"]) as $piece) { $pos = PositionOfPiece($piece); if ($pos != $row["Node1"] && $pos != $row["Node2"] && $pos != $row["Node3"]) $possibleMillMoves[$piece][] = $row["NextMove"]; } } } return $possibleMillMoves; } function AboutToMill($BW) { //returns a list of places the specified player (B or W) could play on their next move to make a Mill global $BoardState, $database; //Get current player positions as comma separated list $currPieces = "(-1" ; foreach ($BoardState as $pieceID => $posID) { if ($pieceID[0] == $BW && $posID != NULL) $currPieces .= ",".$posID; } $currPieces .= ")"; //Get places a mill could be made $querystring = "SELECT Node1 as NextMove, Node1, Node2, Node3 FROM NineMensMills WHERE Node1 NOT IN $currPieces AND Node2 IN $currPieces AND Node3 in $currPieces UNION "; $querystring .= "SELECT Node2 as NextMove, Node1, Node2, Node3 FROM NineMensMills WHERE Node1 IN $currPieces AND Node2 NOT IN $currPieces AND Node3 in $currPieces UNION "; $querystring .= "SELECT Node3 as NextMove, Node1, Node2, Node3 FROM NineMensMills WHERE Node1 IN $currPieces AND Node2 in $currPieces AND Node3 NOT IN $currPieces"; $result = $database->query($querystring); if (!$result) die($databse->lastErrorMsg()); $possibleMills = array(); while ($row = $result->fetchArray(SQLITE3_ASSOC)) { $possibleMills[] = $row; } //Filter out illegal moves, previous mills, etc if (isSetupStage()) { foreach ($possibleMills as $key => $row) { if (!isValidSetupMove($row["NextMove"])) unset($possibleMills[$key]); } } else { //TO-DO } return $possibleMills; } ?>