Ejemplo n.º 1
0
function expandMinefield($minefield, $visibility, $widthToAdd, $minesToAdd)
{
    $height = count($minefield[0]);
    if ($minesToAdd <= 0) {
        $minesToAdd = floor($widthToAdd * $height * 0.15);
        $minesToAdd += count($minefield) / 10;
        $minesToAdd = ceil($minesToAdd);
        $minesToAdd += rand(-10, 10);
    }
    $areaToAdd = createMinefieldArea($widthToAdd, $height, $minesToAdd);
    foreach ($areaToAdd as $key => $value) {
        array_push($minefield, $value);
        array_push($visibility, array_fill(0, $height, 0));
    }
    $minefield = updateMinefieldNumbers($minefield);
    $ret = array("minefield" => $minefield, "visibility" => $visibility);
    return $ret;
}
Ejemplo n.º 2
0
function createNewGame($width, $height, $numMines)
{
    global $sqlhost, $sqlusername, $sqlpassword;
    global $numTraps;
    $gameCreated = false;
    #Initialize the connection to the MySQL database.
    $conn = new mysqli($sqlhost, $sqlusername, $sqlpassword);
    if ($conn->connect_error) {
        die("createNewGame.php - Connection failed: " . $conn->connect_error);
    }
    #Deletes all variables for upcoming game times.
    if ($deleteTimeStmt = $conn->prepare("DELETE FROM sweepelite.globalvars WHERE k='nextGameTime'")) {
        $deleteTimeStmt->execute();
        $deleteTimeStmt->close();
    } else {
        error_log("createNewGame.php - Unable to prepare next game time deletion statement, only cosmetic in effects. " . $conn->errno . ": " . $conn->error);
    }
    #Retrieve all players currently in the sign-up queue and create statuses for them.
    if ($playerStmt = $conn->prepare("SELECT playerID FROM sweepelite.upcomingsignup")) {
        $playerIDs = array();
        $playerStmt->execute();
        $playerStmt->bind_result($curID);
        while ($playerStmt->fetch()) {
            array_push($playerIDs, $curID);
        }
        $playerStmt->close();
        if (count($playerIDs) === 0) {
            error_log("No players for new game, going to wait until one connects.");
        }
        #Creates a double array with all zeroes matching the width and height of the minefield, along with random mines inserted into it.
        $minefield = createMinefieldArea($width, $height, $numMines);
        #Updates the minefield array to have each space without a mine have the number of adjacent mines to it instead of 0.
        $minefield = updateMinefieldNumbers($minefield);
        #Translates the minefield to a form that can be stored in the database.
        $result = translateMinefieldToMySQL($minefield);
        #Creates a generic visibility array of all 'unrevealed' tiles.
        $visibility = str_pad("", strlen($result), "0");
        #Attempt to upload the newly created game into the MySQL database.
        if ($insertStmt = $conn->prepare("INSERT INTO sweepelite.games (map, visibility, height, width, status) VALUES (?,?,?,?,'OPEN')")) {
            $insertStmt->bind_param("ssii", $result, $visibility, $height, $width);
            $inserted = $insertStmt->execute();
            if ($inserted) {
                $insertStmt->close();
                #Retrieve the unique ID of the game just uploaded to the MySQL database.
                if ($idStmt = $conn->prepare("SELECT gameID FROM sweepelite.games WHERE map=? AND status='OPEN' LIMIT 1")) {
                    $idStmt->bind_param("s", $result);
                    $idStmt->execute();
                    $idStmt->bind_result($gameID);
                    $idStmt->fetch();
                    $idStmt->close();
                    if ($gameID !== null) {
                        #Upload all created statuses to the database.
                        if ($statusStmt = $conn->prepare("INSERT INTO sweepelite.playerstatus (gameID, playerID, trapType, awaitingAction) VALUES (?, ?, ?, 1)")) {
                            for ($i = 0; $i < count($playerIDs); $i++) {
                                $trapID = ($gameID + $playerIDs[$i]) % $numTraps;
                                $statusStmt->bind_param("iii", $gameID, $playerIDs[$i], $trapID);
                                $statusStmt->execute();
                            }
                            $statusStmt->close();
                            #Delete everyone from the sign-up queue.
                            if ($deleteStmt = $conn->prepare("TRUNCATE sweepelite.upcomingsignup")) {
                                #$deleteStmt->execute();
                                $deleteStmt->close();
                                $gameCreated = true;
                                #Successfully created the new game.
                                error_log("createNewGame.php - New game successfully created, ID=" . $gameID);
                                return $gameID;
                            } else {
                                error_log("createNewGame.php - Unable to prepare delete statement. " . $conn->errno . ": " . $conn->error);
                            }
                        } else {
                            error_log("createNewGame.php - Unable to prepare sign-up finalize statement. " . $conn->errno . ": " . $conn->error);
                        }
                    } else {
                        error_log("createNewGame.php - Unexpected results from ID statement. " . $idStmt->errno . ": " . $idStmt->error);
                    }
                } else {
                    error_log("createNewGame.php - Unable to prepare ID statement. " . $conn->errno . ": " . $conn->error);
                }
            } else {
                error_log("createNewGame.php - Unable to insert game during creation. " . $insertStmt->errno . ": " . $insertStmt->error);
            }
        } else {
            error_log("createNewGame.php - Unable to prepare game insertation statement. " . $conn->errno . ": " . $conn->error);
        }
    } else {
        error_log("createNewGame.php - Unable to prepare sign-up statement. " . $conn->errno . ": " . $conn->error);
    }
    if (!$gameCreated) {
        error_log("createNewGame.php - Unable to create new game, returning -1.");
    }
    return false;
}
Ejemplo n.º 3
0
function resolveAllActions($gameID)
{
    global $sqlhost, $sqlusername, $sqlpassword, $adjacencies;
    #Initialize the connection to the MySQL database.
    $conn = new mysqli($sqlhost, $sqlusername, $sqlpassword);
    if ($conn->connect_error) {
        die("resolveActions.php - Connection failed: " . $conn->connect_error);
    }
    #Get map information, both the minefield and the visibility, for this game.
    if ($stmt = $conn->prepare("SELECT map, visibility, height, width, friendlyTankCountdown, friendlyTanks, enemyTankCountdown, enemyTankCountdownReset, enemyTanks, wrecks, traps FROM sweepelite.games WHERE gameID=?")) {
        $stmt->bind_param("i", $gameID);
        $stmt->execute();
        $stmt->bind_result($m, $v, $h, $w, $tankCount, $t, $enemyTankCount, $enemyTankReset, $e, $wr, $tr);
        if ($stmt->fetch()) {
            $stmt->close();
            #Determine if this is the first ever move in the game. If so, different actions call for different outcomes.
            $firstMove = false;
            if (strpos($v, "1") === false && strpos($v, "2") === false) {
                $firstMove = true;
            }
            $minefield = translateMinefieldToPHP($m, $h, $w);
            $visibility = translateMinefieldToPHP($v, $h, $w);
            $friendlyTanks = translateTanksToPHP($t);
            $enemyTanks = translateTanksToPHP($e);
            $wrecks = translateTanksToPHP($wr);
            $traps = translateTrapsToPHP($tr);
            #Determine if we need to expand the map first due to tank movement.
            $expand = false;
            $baseExploded = false;
            foreach ($friendlyTanks as $tankKey => $tankPos) {
                if ($tankPos[0] == $w - 1) {
                    $expand = true;
                }
            }
            foreach ($enemyTanks as $tankKey => $tankPos) {
                if ($tankPos[0] == 0) {
                    $baseExploded = true;
                }
            }
            if ($expand) {
                $newVals = expandMinefield($minefield, $visibility, 10, 0);
                $minefield = $newVals["minefield"];
                $visibility = $newVals["visibility"];
                if ($enemyTankReset > 3) {
                    $enemyTankReset = $enemyTankReset - 1;
                }
            }
            #Get all player information
            $allPlayers = getPlayersForGame($gameID);
            if (count($allPlayers) > 0) {
                #Retrieve all actions in the action queue for this game and throw them into unique objects in an array for easy access during resolution.
                if ($actionStmt = $conn->prepare("SELECT playerID, actionType, xCoord, yCoord FROM sweepelite.actionqueue WHERE gameID=?")) {
                    $actionqueue = array();
                    $actionStmt->bind_param("i", $gameID);
                    $actionStmt->execute();
                    $actionStmt->bind_result($playerID, $actionType, $xCoord, $yCoord);
                    while ($actionStmt->fetch()) {
                        $temp = array("playerID" => intval($playerID), "actionType" => intval($actionType), "x" => intval($xCoord), "y" => intval($yCoord));
                        array_push($actionqueue, $temp);
                    }
                    $actionStmt->close();
                    $queuedTraps = array();
                    while (count($actionqueue) > 0) {
                        $cur = array_shift($actionqueue);
                        #Check that current action is legal according to tank placement.
                        $legalMove = true;
                        foreach ($friendlyTanks as $tankKey => $tankPos) {
                            if ($cur['x'] == $tankPos[0]) {
                                if ($cur['y'] == $tankPos[1]) {
                                    $legalMove = false;
                                }
                            }
                        }
                        foreach ($enemyTanks as $tankKey => $tankPos) {
                            if ($cur['x'] == $tankPos[0]) {
                                if ($cur['y'] == $tankPos[1]) {
                                    $legalMove = false;
                                }
                            }
                        }
                        foreach ($wrecks as $wkey => $wval) {
                            if ($cur['x'] == $wval[0]) {
                                if ($cur['y'] == $wval[1]) {
                                    $legalMove = false;
                                }
                            }
                        }
                        foreach ($traps as $wkey => $tval) {
                            if ($cur['x'] == $tval[1]) {
                                if ($cur['y'] == $tval[2]) {
                                    $legalMove = false;
                                }
                            }
                        }
                        if ($legalMove) {
                            #Action Type 0 is a shovel action.
                            #When shoveling, the current tile is revealed no matter what.
                            #If the tile is a mine, this kills the current player.
                            #If the tile had a value of 0, new actions are added to the queue for revealing all adjacent tiles to the shoveled tile, barring any that are already not flagged or visible.
                            if ($cur["actionType"] === 0) {
                                #Check if we have previously shoveled this tile or not.
                                $notShoveled = true;
                                foreach (getPlayerValue($allPlayers, $cur["playerID"], "dugTiles") as $key => $shoveled) {
                                    if ($cur['x'] == $shoveled[0]) {
                                        if ($cur['y'] == $shoveled[1]) {
                                            $notShoveled = false;
                                        }
                                    }
                                }
                                if ($notShoveled) {
                                    $visibility[$cur["x"]][$cur["y"]] = 2;
                                    if ($minefield[$cur["x"]][$cur["y"]] === "M") {
                                        if ($firstMove) {
                                            #Temporarily just remove the mine.
                                            $minefield[$cur["x"]][$cur["y"]] = 0;
                                            $visibility[$cur["x"]][$cur["y"]] = 0;
                                            $minefield = updateMinefieldNumbers($minefield);
                                            $newAction = array("playerID" => $cur["playerID"], "actionType" => $cur["actionType"], "x" => $cur["x"], "y" => $cur["y"]);
                                            array_push($actionqueue, $newAction);
                                        } else {
                                            $tempDugTiles = getPlayerValue($allPlayers, $cur["playerID"], "dugTiles");
                                            array_push($tempDugTiles, array($cur["x"], $cur["y"]));
                                            $allPlayers = setPlayerValue($allPlayers, $cur["playerID"], "dugTiles", $tempDugTiles);
                                            $allPlayers = setPlayerValue($allPlayers, $cur["playerID"], 'status', 0);
                                        }
                                    } else {
                                        if ($minefield[$cur["x"]][$cur["y"]] == 0) {
                                            $tempDugTiles = getPlayerValue($allPlayers, $cur["playerID"], "dugTiles");
                                            array_push($tempDugTiles, array($cur["x"], $cur["y"]));
                                            $allPlayers = setPlayerValue($allPlayers, $cur["playerID"], "dugTiles", $tempDugTiles);
                                            foreach ($adjacencies as $adj) {
                                                $targetX = $cur["x"] + $adj[0];
                                                $targetY = $cur["y"] + $adj[1];
                                                $shouldAdd = true;
                                                if ($targetX < 0 or $targetX >= $w) {
                                                    $shouldAdd = false;
                                                }
                                                if ($targetY < 0 or $targetY >= $h) {
                                                    $shouldAdd = false;
                                                }
                                                if ($shouldAdd) {
                                                    $noTanks = true;
                                                    foreach ($friendlyTanks as $tankKey => $tankPos) {
                                                        if ($targetX == $tankPos[0]) {
                                                            if ($targetY == $tankPos[1]) {
                                                                $noTanks = false;
                                                            }
                                                        }
                                                    }
                                                    foreach ($enemyTanks as $tankKey => $tankPos) {
                                                        if ($targetX == $tankPos[0]) {
                                                            if ($targetY == $tankPos[1]) {
                                                                $noTanks = false;
                                                            }
                                                        }
                                                    }
                                                    foreach ($wrecks as $wkey => $wval) {
                                                        if ($targetX == $wval[0]) {
                                                            if ($targetY == $wval[1]) {
                                                                $noTanks = false;
                                                            }
                                                        }
                                                    }
                                                    if ($noTanks) {
                                                        if ($visibility[$targetX][$targetY] == 0) {
                                                            $newAction = array("playerID" => $cur["playerID"], "actionType" => $cur["actionType"], "x" => $targetX, "y" => $targetY);
                                                            array_push($actionqueue, $newAction);
                                                        }
                                                    }
                                                }
                                            }
                                        } else {
                                            $tempDugTiles = getPlayerValue($allPlayers, $cur["playerID"], "dugTiles");
                                            array_push($tempDugTiles, array($cur["x"], $cur["y"]));
                                            $allPlayers = setPlayerValue($allPlayers, $cur["playerID"], "dugTiles", $tempDugTiles);
                                        }
                                    }
                                }
                                #Action Type 1 is a flag action.
                                #If the tile is unrevealed, a flag is placed there instead.
                            } else {
                                if ($cur["actionType"] === 1) {
                                    if ($visibility[$cur["x"]][$cur["y"]] == 0) {
                                        $visibility[$cur["x"]][$cur["y"]] = 1;
                                        if ($minefield[$cur["x"]][$cur["y"]] === "M") {
                                            $allPlayers = alterPlayerValue($allPlayers, $cur["playerID"], "correctFlags", 1);
                                        }
                                        $allPlayers = alterPlayerValue($allPlayers, $cur["playerID"], "flagNumber", 1);
                                    }
                                    #Action Type 2 is a place trap action.
                                    #Place a trap on the space.
                                } else {
                                    if ($cur["actionType"] === 2) {
                                        $cooldown = getPlayerValue($allPlayers, $cur["playerID"], "trapCooldown");
                                        if ($cooldown <= 0) {
                                            $trapVal = getPlayerValue($allPlayers, $cur["playerID"], "trapType");
                                            $tempTrap = array($trapVal, $cur["x"], $cur["y"]);
                                            array_push($queuedTraps, $tempTrap);
                                            $allPlayers = setPlayerValue($allPlayers, $cur["playerID"], "trapCooldown", getCooldownForTrapType($trapVal));
                                        }
                                    }
                                }
                            }
                        } else {
                            error_log("resolveActions.php - Illegal move made by player ID " . $cur["playerID"] . " at coordinates " . $cur["x"] . "," . $cur["y"]);
                        }
                        if (getPlayerValue($allPlayers, $cur['playerID'], 'hasActed') === 0) {
                            if ($cur['actionType'] === 0) {
                                $oldCooldown = getPlayerValue($allPlayers, $cur['playerID'], 'trapCooldown');
                                if ($oldCooldown > 0) {
                                    $allPlayers = setPlayerValue($allPlayers, $cur['playerID'], 'trapCooldown', $oldCooldown - 1);
                                }
                            }
                        }
                        $allPlayers = setPlayerValue($allPlayers, $cur['playerID'], 'hasActed', 1);
                    }
                    #Resolve traps
                    $trapResults = resolveTraps($minefield, $visibility, $friendlyTanks, $enemyTanks, $traps, $wrecks);
                    $traps = $trapResults['traps'];
                    #Add queued traps
                    foreach ($queuedTraps as $trapKey => $trapSpecifics) {
                        $traps = addTrap($traps, $trapSpecifics[0], $trapSpecifics[1], $trapSpecifics[2]);
                    }
                    #All tanks are updated, and any stuff on the map is updated to reflect these changes.
                    $updatedTanks = updateTanks($trapResults['map'], $trapResults['visibility'], $trapResults['friendlyTanks'], $trapResults['enemyTanks'], $trapResults['wrecks']);
                    $friendlyTanks = $updatedTanks['updatedFriendlyTanks'];
                    $enemyTanks = $updatedTanks['updatedEnemyTanks'];
                    $wrecks = $updatedTanks['updatedWrecks'];
                    $visibility = $updatedTanks['updatedVisibility'];
                    #Update the tank count. If it is at 0, add a tank and reset the count to 3.
                    $tankCount = $tankCount - 1;
                    if ($tankCount <= 0) {
                        $addedTank = addFriendlyTank($minefield, $visibility);
                        if ($addedTank['newTankPosition'] !== null) {
                            array_push($friendlyTanks, $addedTank['newTankPosition']);
                        }
                        if ($addedTank['newVisibility'] !== null) {
                            $visibility = $addedTank['newVisibility'];
                        }
                        $tankCount = 3;
                    }
                    #Update the enemy tank count. If it is at 0, add an enemy and reset the count to the current threshold.
                    $enemyTankCount = $enemyTankCount - 1;
                    if ($enemyTankCount <= 0) {
                        $addedTank = addEnemyTank($minefield, $visibility);
                        if ($addedTank['newTankPosition'] !== null) {
                            array_push($enemyTanks, $addedTank['newTankPosition']);
                        }
                        if ($addedTank['newVisibility'] !== null) {
                            $visibility = $addedTank['newVisibility'];
                        }
                        $enemyTankCount = $enemyTankReset;
                    }
                    #All players who did submit actions are updated appropriately.
                    $allPlayers = savePlayersForGame($allPlayers, $gameID);
                    #Empty the action queue of actions relating to this specific game.
                    if ($deleteStmt = $conn->prepare("DELETE FROM sweepelite.actionqueue WHERE gameID=?")) {
                        $deleteStmt->bind_param("i", $gameID);
                        $updated = $deleteStmt->execute();
                        if ($updated === false) {
                            error_log("resolveActions.php - Error occurred during action queue clean up. " . $deleteStmt->errno . ": " . $deleteStmt->error);
                            $deleteStmt->close();
                        } else {
                            $deleteStmt->close();
                            #Try to determine if the game is complete or not.
                            $gameCompleted = false;
                            if ($baseExploded) {
                                $gameCompleted = true;
                                error_log("Game Over - Base blown up!");
                            } else {
                                if (countPlayersWithValue($allPlayers, 'status', 1) > 0) {
                                    $gameCompleted = true;
                                    for ($x = 0; $x < count($visibility) && $gameCompleted; $x++) {
                                        for ($y = 0; $y < count($visibility[$x]) && $gameCompleted; $y++) {
                                            if ($visibility[$x][$y] == 0) {
                                                if ($minefield[$x][$y] === "M") {
                                                    $gameCompleted = false;
                                                }
                                            }
                                        }
                                    }
                                    if ($gameCompleted) {
                                        error_log("Game Over - No unrevealed non-mine tiles left!");
                                    }
                                } else {
                                    $gameCompleted = true;
                                    error_log("Game Over - No living players left!");
                                }
                            }
                            #If game is done, all unrevealed tiles become visible instead.
                            if ($gameCompleted) {
                                for ($x = 0; $x < count($visibility); $x++) {
                                    for ($y = 0; $y < count($visibility[$x]); $y++) {
                                        if ($minefield[$x][$y] === "M") {
                                            $visibility[$x][$y] = 2;
                                        }
                                    }
                                }
                                $allPlayers = setAllPlayersValue($allPlayers, "status", 0);
                                savePlayerScores($allPlayers);
                            }
                            #Update map and visibility values for the game by saving to database.
                            if ($updateStmt = $conn->prepare("UPDATE sweepelite.games SET map=?, visibility=?, friendlyTankCountdown=?, friendlyTanks=?, enemyTankCountdown=?, enemyTanks=?, enemyTankCountdownReset=?, wrecks=?, traps=?, status=?, width=?, height=?, lastUpdated=NOW(), fullUpdate=1 WHERE gameID=?")) {
                                $statusStr = "OPEN";
                                if ($gameCompleted) {
                                    $statusStr = "GAME OVER";
                                }
                                $updateStmt->bind_param("ssisisisssiii", translateMinefieldToMySQL($minefield), translateMinefieldToMySQL($visibility), $tankCount, translateTanksToMySQL($friendlyTanks), $enemyTankCount, translateTanksToMySQL($enemyTanks), $enemyTankReset, translateTanksToMySQL($wrecks), translateTrapsToMySQL($traps), $statusStr, count($minefield), count($minefield[0]), $gameID);
                                $updated = $updateStmt->execute();
                                if ($updated === false) {
                                    error_log("resolveActions.php - Error occurred during map update. " . $updateStmt->errno . ": " . $updateStmt->error);
                                }
                                $updateStmt->close();
                                if ($gameCompleted) {
                                    return false;
                                }
                            } else {
                                error_log("resolveActions.php - Unable to prepare map update after resolving action queue. " . $conn->errno . ": " . $conn->error);
                            }
                        }
                    } else {
                        error_log("resolveActions.php - Unable to prepare delete statement. " . $conn->errno . ": " . $conn->error);
                    }
                } else {
                    error_log("resolveActions.php - Unable to prepare action statement for resolving action queue. " . $conn->errno . ": " . $conn->error);
                }
            } else {
                error_log("resolveActions.php - Did not find any players for current game.");
            }
        } else {
            error_log("resolveActions.php - Unable to resolve map statement for resolving action queue. " . $stmt->errno . ": " . $stmt->error);
        }
    } else {
        error_log("resolveActions.php - Unable to prepare map statement for resolving action queue. " . $conn->errno . ": " . $conn->error);
    }
    return true;
}