// TIC TAC TOE // A server script for ArtyOnline server application // by Arty-fishL // 4 Aug 2012 /* ---------- * IMPORTS */ /* ---------- * VARIABLES */ var started = false, xPlayer = null, oPlayer = null, mrStage = 0, readyX = false, readyO = false, whosGo = null; // board var line1 = [0, 0, 0], line2 = [0, 0, 0], line3 = [0, 0, 0]; /* ---------- * FUNCTIONS */ function menuDisplayPlayers() { // shows who is playing if(xPlayer != null) print("X: " + xPlayer.getUsername()); else print("X: NOT SET YET"); if(oPlayer != null) print("O: " + oPlayer.getUsername()); else print("O: NOT SET YET"); } function menuDisplayBoard() { // shows the current game board print("_____"); var board = [line1, line2, line3]; for(v in board) { var text = " "; for(i in board[v]) { if(board[v][i] === 1) text += "X "; else if(board[v][i] === 2) text += "O "; else text += "# "; } print(text); } print("_____"); } function menuInformHurryUp() { // tell the current player to hurry up if(whosGo != null) { print("Telling " + whosGo.getUsername() + " to hurry up"); var message = Messages.SimpleMessage(whosGo, Messages.MessageBank.get("hurry up"), []); Messages.sendMessage(message); } else { print("ERROR: The game has not started yet"); } } function setupCustomMenu() { // sets up a custom menu for the server application var customMenu = AppUtil.SimpleMenu("Game"); displayPlayersItem = AppUtil.SimpleMenu.SimpleMenuItem("Display Players", menuDisplayPlayers); displayBoardItem = AppUtil.SimpleMenu.SimpleMenuItem("Display Game Board", menuDisplayBoard); hurryUpItem = AppUtil.SimpleMenu.SimpleMenuItem("Tell Current Player To Hurry Up", menuInformHurryUp); customMenu.add(displayPlayersItem); customMenu.add(displayBoardItem); customMenu.add(hurryUpItem); AppUtil.enableCustomGuiScriptMenu(customMenu); } function setupGame() { // randomly choose x and o player if (Math.round( Math.random() ) === 0) { // first player is x xPlayer = Users.getUsers()[0]; oPlayer = Users.getUsers()[1]; } else { // second player is x xPlayer = Users.getUsers()[1]; oPlayer = Users.getUsers()[0]; } // randomly choose who plays first if (Math.round( Math.random() ) === 0) { // x goes first whosGo = xPlayer; } else { // o goes first whosGo = oPlayer; } // inform who is playing what print("X: " + xPlayer.getUsername() + ", O: " + oPlayer.getUsername()); var xoro = null; if(whosGo.getUsername() === xPlayer.getUsername()) { xoro = "X"; } else { xoro = "O"; } print(whosGo.getUsername() + " (" + xoro + ") is playing first"); var message = Messages.SimpleMessage(xPlayer, Messages.MessageBank.get("play as"), Messages.Var.getVarsFromArray(["x", (whosGo === xPlayer), oPlayer.getUsername()])); Messages.sendMessage(message); message = Messages.SimpleMessage(oPlayer, Messages.MessageBank.get("play as"), Messages.Var.getVarsFromArray(["o", (whosGo === oPlayer), xPlayer.getUsername()])); Messages.sendMessage(message); // replies will be received in onMessageReceived event mrStage = 1; } function replyWhoXO(message) { // - reply to who is x and o if (message.getMessage() === Messages.MessageBank.get("understood")) { // confirmed player is ready if (message.getUser().getUsername() === xPlayer.getUsername()) { readyX = true; } else if (message.getUser().getUsername() === oPlayer.getUsername()) { readyO = true; } else { print("ERROR: Invalid user - " + message.getUser().getUsername()); } // if both players are ready start play if (readyX && readyO) { // let play commence print("Both players ready, let play commence"); mrStage = 2; informNextMove(); } } else { print("ERROR: Invalid message with code: " + message.getMessage().toString()) // somebody didnt understand, try sending again var message2 = null; if (message.getUser().getUsername() === xPlayer.getUsername()) { message2 = Messages.SimpleMessage(message.getUser(), Messages.MessageBank.get("play as"), [Messages.Var("x")]); } else if (message.getUser().getUsername() === oPlayer.getUsername()) { message2 = Messages.SimpleMessage(message.getUser(), Messages.MessageBank.get("play as"), [Messages.Var("o")]); } Messages.sendMessage(message2); } } function changePlayer() { // next persons go if (whosGo.getUsername() === xPlayer.getUsername()) { whosGo = oPlayer; } else { whosGo = xPlayer; } } function checkForWin() { // check to see if a player has won var sequence = line1.concat(line2, line3), winningSequences = [ ["tl", "tm", "tr"] , ["ml", "mm", "mr"] , ["bl", "bm", "br"] , ["tl", "ml", "bl"] , ["tm", "mm", "bm"] , ["tr", "mr", "br"] , ["tl", "mm", "br"] , ["tr", "mm", "bl"] ], playingPiece = 0; if (whosGo.getUsername() === xPlayer.getUsername()) { playingPiece = 1; } else { playingPiece = 2; } var placeMap = { 0: "tl", 1: "tm", 2: "tr", 3: "ml", 4: "mm", 5: "mr", 6: "bl", 7: "bm", 8: "br" }, playedPlaces = []; for (i=0; i<9; i++) { if (sequence[i] === playingPiece) { playedPlaces.push(placeMap[i]); } } for (i=0; i < winningSequences.length; i++) { if (playedPlaces.indexOf(winningSequences[i][0]) > -1 && playedPlaces.indexOf(winningSequences[i][1]) > -1 && playedPlaces.indexOf(winningSequences[i][2]) > -1) { // matched a winning sequence return true; } } // no winning matches return false; } function checkForTie() { // check to see if no player has won var board = [line1, line2, line3]; for(v in board) { for(i in board[v]) { if(board[v][i] === 0) // found an empty space, so cannot be a tie return false; } } // no 0 (empty space) found, is a tie return true } function informCurrentMove(line, box) { var xoro = null; if(whosGo.getUsername() === xPlayer.getUsername()) { xoro = "X"; } else { xoro = "O"; } print(whosGo.getUsername() + " placed an " + xoro + " at (" + (box + 1).toString() + ", " + line.toString() + ")"); var mp = null; if (whosGo.getUsername() === xPlayer.getUsername()) { mp = oPlayer; } else { mp = xPlayer; } var message = Messages.SimpleMessage(mp, Messages.MessageBank.get("other player moved"), Messages.Var.getVarsFromArray([line, box])); Messages.sendMessage(message); } function informNextMove() { var xoro = null; if(whosGo.getUsername() === xPlayer.getUsername()) { xoro = "X"; } else { xoro = "O"; } print("It is now " + whosGo.getUsername() + "'s (" + xoro + ") go"); var message = Messages.SimpleMessage(whosGo, Messages.MessageBank.get("your go"), []); Messages.sendMessage(message); } function informWinner() { var winner = ""; if (whosGo.getUsername() === xPlayer.getUsername()) { winner = "X"; print("X won (" + xPlayer.getUsername() + ")"); } else { winner = "O"; print("O won (" + oPlayer.getUsername() + ")"); } var message = Messages.SimpleMessage(xPlayer, Messages.MessageBank.get("winner"), [Messages.Var(winner)]); Messages.sendMessage(message); message = Messages.SimpleMessage(oPlayer, Messages.MessageBank.get("winner"), [Messages.Var(winner)]); Messages.sendMessage(message); } function informTie() { var winner = "tie"; var message = Messages.SimpleMessage(xPlayer, Messages.MessageBank.get("winner"), [Messages.Var(winner)]); Messages.sendMessage(message); message = Messages.SimpleMessage(oPlayer, Messages.MessageBank.get("winner"), [Messages.Var(winner)]); Messages.sendMessage(message); } function makeMove(message) { // current player chose position var line = message.getVars()[0].asInt(); box = message.getVars()[1].asInt(); xo = 0; if( (0 < line < 4) && (0 <= box < 3) ) { // valid move if (whosGo.getUsername() === xPlayer.getUsername()) { xo = 1; } else { xo = 2; } if(line === 1) { // play in line 1 line1[box] = xo; } else if(line === 2) { // play in line 2 line2[box] = xo; } else if(line === 3) { // play in line 3 line3[box] = xo; } // use move data informCurrentMove(line, box); if (checkForWin() === false) { if (checkForTie() === false) { // next move changePlayer(); informNextMove(); } else { // tie game resetBoard(); informTie(); changePlayer(); } } else { // somebody won resetBoard(); informWinner(); changePlayer(); } } else { // invalid move // kick player for possible cheating message.getUser().kick("Invalid move was played") } } function resetBoard() { // reset for a new round line1 = [0, 0, 0]; line2 = [0, 0, 0]; line3 = [0, 0, 0]; readyX = false; readyY = false; mrStage = 3; } function startNewRound(message) { // game is over and player is ready to start a new round if (message.getUser().getUsername() === xPlayer.getUsername()) { readyX = true; } else if (message.getUser().getUsername() === oPlayer.getUsername()) { readyO = true; } else { print("ERROR: Invalid user - " + message.getUser().getUsername()); } // if both players are ready start round if (readyX && readyO) { // let round commence print("\nNew round"); print("Both players ready, let play commence"); mrStage = 2; informNextMove(); } } /* --------- * EVENTS */ Events.onLoad = function(vars) { // SETUP // limit players to 2 Users.setMaxUsers(2); // add messages to message bank Messages.MessageBank.add( ["wait other player", "play as", "understood", "your go", "make move", "other player moved", "winner", "hurry up", "ready next round"] ); // setup custom menu setupCustomMenu(); }; Events.onJoin = function(vars){ // wait for 2 players to join if (Users.getUsers().length === 2) { // start game print("Game started"); started = true; setupGame(); } else { // still waiting for players to join print("Waiting for other player to join"); // inform user who just joined var message = Messages.SimpleMessage(vars[0], Messages.MessageBank.get("wait other player"), []); Messages.sendMessage(message); } }; Events.onDisconnect = function(vars){ // wait for 2 players to be in game again if (Users.getUsers().length < 2) { // not enough players print("Not enough players in game"); print("Restarting server ..."); AppUtil.restartApplication(); } }; Events.onMessageReceive = function(vars) { // get message var message = vars[0]; // check for various functions if (mrStage === 1) { // reply to who is x and o replyWhoXO(message); } else if (mrStage === 2 && message.getMessage() === Messages.MessageBank.get("make move") && message.getUser().getUsername() === whosGo.getUsername()) { // telling where player will move makeMove(message); } else if (mrStage === 3 && message.getMessage() === Messages.MessageBank.get("ready next round")) { // telling where player will move startNewRound(message); } }; Events.onCommand = function(vars) { // print understood var command = vars[0]; //print(command.getCommand()); };