diff --git a/games/tic-tac-toe-js/css/screen.css b/games/tic-tac-toe-js/css/screen.css index d31c57d..5d09712 100644 --- a/games/tic-tac-toe-js/css/screen.css +++ b/games/tic-tac-toe-js/css/screen.css @@ -1,5 +1,6 @@ body { text-align: center; + font-family: "Lucida Grande", Tahoma, Helvetica, Verdana, sans-serif; } table { diff --git a/games/tic-tac-toe-js/index.html b/games/tic-tac-toe-js/index.html index bb008f9..6df9733 100644 --- a/games/tic-tac-toe-js/index.html +++ b/games/tic-tac-toe-js/index.html @@ -2,11 +2,32 @@ Tic Tac Toe - + + + + + - -
-

New game

- + + + + + + + <body> + <h1>Tic Tac Toe for Generic Game Server</h1> + <p>This simulator only works with frames.</p> + </body> + + \ No newline at end of file diff --git a/games/tic-tac-toe-js/js/GGS.js b/games/tic-tac-toe-js/js/GGS.js new file mode 100644 index 0000000..1b92ff7 --- /dev/null +++ b/games/tic-tac-toe-js/js/GGS.js @@ -0,0 +1,16 @@ +function GGSI(game_name) { + var world = new Storage(game_name, "world"); + this.__defineGetter__("world", function(){ + return world; + }); + + var localStorage = new Storage(game_name, "localStorage"); + this.__defineGetter__("localStorage", function(){ + return localStorage; + }); + + var game_n = game_name; + this.__defineGetter__("users", function(){ + return GameServerI.users(game_n); + }); +} diff --git a/games/tic-tac-toe-js/js/GameServer.js b/games/tic-tac-toe-js/js/GameServer.js new file mode 100644 index 0000000..dc752b8 --- /dev/null +++ b/games/tic-tac-toe-js/js/GameServer.js @@ -0,0 +1,183 @@ +// This is just a simulator of a game server to find +// out which methods we need. This will be rewritten +// in erlang. + +// Game main() function should return a instance of the game +// Game Methods: +// userAllowed() op +// userAdded() op +// userCommand() m + +function GameServer() { + this.init(); +} +GameServer.prototype.init = function() { + this.games = {}; +} + +GameServer.prototype.addGame = function(game_name, instance) { + if (typeof game_name == "string" && game_name != "" && typeof instance == "object") { + var aGame = { + instance: instance, + users: [], + world: {}, + localStorage: {} + } + this.games[game_name] = aGame; + this.games[game_name].users + } else throw "GGS: Could not add game " + game_name; +} + +GameServer.prototype.addClient = function(game_name, client) { + var game = this.games[game_name]; + if (typeof game != "undefined") { + if (typeof game.instance.userAllowed == "undefined" || typeof game.instance.userAllowed == "function" && game.instance.userAllowed(user)) { + var user = new User(game.users.length, client); + game.users.push(user); + if (typeof game.instance.userAdded == "function") { + game.instance.userAdded(user); + } + } else throw "GGS: Unable to add client to game " + game_name; + } else throw "GGS: No such game " + game_name; +} + +GameServer.prototype.users = function(game_name) { + var game = this.games[game_name]; + if (game != "undefined") { + return game.users; + } else throw "GGS: Unknown game " + game_name; +} + +// Client calls this command, just a convinience method in the simulator +GameServer.prototype.callCommand = function(game_name, client, command, attrs) { + var game = this.games[game_name]; + if (typeof game != "undefined") { + if(typeof game.instance.userCommand == "function") { + var user = null; + for (var i=0; i < game.users.length; i++) { + if (game.users[i].client == client) { + user = game.users[i]; + } + } + if (user != null) { + game.instance.userCommand(user, command, attrs); + } else throw "GGS: User not allowed"; + } else throw "GGS: No such method userCommand() in game " + game_name; + } else throw "GGS: No such game " + game_name; +} + +GameServer.prototype.set = function(game_name, type, key, value) { + var game = this.games[game_name]; + if (game != "undefined") { + if (type == "world" || type == "localStorage") { + if (typeof key == "string" && (typeof value == "string" || typeof value == "number")) { + game[type][key] = value; + if (type == "world") { + var args = {}; + args[key] = JSON.parse(value); + for (var i=0; i < game.users.length; i++) { + game.users[i].sendCommand("world_set", JSON.stringify(args)); + } + } + } else throw "GGS: Key has to be a string and value string or number"; + } else throw "GGS: Unknown type " + type; + } else throw "GGS: No such game" + game_name; +} + +GameServer.prototype.get = function(game_name, type, key) { + var game = this.games[game_name]; + if (game != "undefined") { + return game[type][key]; + } else throw "GGS: No such game" + game_name; +} + +GameServer.prototype.key = function(game_name, type, position) { + var game = this.games[game_name]; + if (game != "undefined") { + var i = 0; + for (var key in game[type]) { + if(i++ == position) { + return key; + } + } + return null; + } else throw "GGS: No such game" + game_name; +} + +GameServer.prototype.length = function(game_name, type) { + var game = this.games[game_name]; + if (game != "undefined") { + var l = 0; + for (var i in game[type]) { + l++; + } + return l; + } else throw "GGS: No such game" + game_name; +} + +GameServer.prototype.remove = function(game_name, type) { + var game = this.games[game_name]; + if (game != "undefined") { + delete game[key]; + } else throw "GGS: Unknown game " + game_name +} + +GameServer.prototype.clear = function(game_name, type) { + var game = this.games[game_name]; + if (game != "undefined") { + game = {}; + } else throw "GGS: Unknown game " + game_name +} + +var GameServerI = new GameServer(); + + + + +// User object +// to talk to the client it should have implemented +// the method commandCalled +function User(id, client) { + var id = id; + var client = client; + + return { + id: id, + client: client, + sendCommand: function(command, args) { + client.commandCalled(command, args); + } + } +} + + +function Storage(game_name, type) { + if (type == "world" || type == "localStorage") { + this.type = type; + this.gameName = game_name; + var self = this; + + return { + setItem: function(key, value) { + GameServerI.set(self.gameName, self.type, key, value); + }, + getItem: function(key) { + return GameServerI.get(self.gameName, self.type, key); + }, + key: function(position) { + return GameServerI.key(self.gameName, self.type, position); + }, + length: { + get: function() { + return GameServerI.length(self.gameName, self.type); + } + }, + removeItem: function(key) { + GameServerI.remove(self.gameName, self.type, key); + }, + clear: function() { + GameServerI.clear(self.gameName, self.type); + } + } + } else throw "GGS: No such storage available " + type; +} diff --git a/games/tic-tac-toe-js/js/TicTacToe.js b/games/tic-tac-toe-js/js/TicTacToe.js new file mode 100644 index 0000000..2d47974 --- /dev/null +++ b/games/tic-tac-toe-js/js/TicTacToe.js @@ -0,0 +1,139 @@ +function TicTacToe() {}; +TicTacToe.prototype.init = function() { + +} + +TicTacToe.prototype.userAllowed = function(user) { + if(GGS.users.length <= 2) return true + else return false; +} + +TicTacToe.prototype.userAdded = function(user) { + GGS.localStorage.setItem("p" + GGS.users.length + "_id", user.id); + + if (GGS.users.length == 2) { + GGS.world.setItem("game_board", JSON.stringify(this.newGameBoard(3))); + GGS.localStorage.setItem("next_player", 1); + this.getUser(GGS.localStorage.getItem("p1_id")).sendCommand("yourturn"); + } +} + +TicTacToe.prototype.getUser = function(user_id) { + for (var i=0; i < GGS.users.length; i++) { + if(GGS.users[i].id == user_id) { + return GGS.users[i]; + } + } +} + +TicTacToe.prototype.newGameBoard = function(rows) { + // Initiate game with empty rows and columns + var gameBoard = []; + for (var i=0; i < rows; i++) { + gameBoard[i] = []; + for (var j=0; j < rows; j++) { + gameBoard[i][j] = 0; + } + } + return gameBoard; +} + +TicTacToe.prototype.userCommand = function(user, command, args) { + var nextPlayer = GGS.localStorage.getItem("next_player"); + var p1_id = GGS.localStorage.getItem("p1_id"); + var p2_id = GGS.localStorage.getItem("p2_id"); + var valid = false; + + if(nextPlayer == 1 && user.id == p1_id) { + valid = true; + } else if (nextPlayer == 2 && user.id == p2_id) { + valid = true; + } + + if (valid) { + if (command == "set") { + + var p = nextPlayer; + var props = JSON.parse(args); + var gameBoard = JSON.parse(GGS.world.getItem("game_board")); + + if (gameBoard[props.x][props.y] == 0) { + gameBoard[props.x][props.y] = p; + GGS.world.setItem("game_board", JSON.stringify(gameBoard)) + if (this.checkIfWon(p, gameBoard)) { + if (p == 1) { + this.getUser(p1_id).sendCommand("winner", "You win!"); + this.getUser(p2_id).sendCommand("loser", "You lose!"); + } else { + this.getUser(p1_id).sendCommand("loser", "You lose!"); + this.getUser(p2_id).sendCommand("winner", "You win!"); + } + } + + if (nextPlayer == 1) { + GGS.localStorage.setItem("next_player", 2); + this.getUser(p1_id).sendCommand("yourturn"); + } else { + GGS.localStorage.setItem("next_player", 1); + this.getUser(p2_id).sendCommand("yourturn"); + } + + } else { + user.sendCommand("warning", "Already set, chose something else."); + } + } else throw "TTTS: Unknown command " + command; + } else { + user.sendCommand("warning", "Not your turn!"); + } +} + +TicTacToe.prototype.checkIfWon = function(player, gameBoard) { + + var rows = gameBoard.length; + + for (i = 0; i < rows; ++i) { + for (j = 0; j < rows; ++j) { + if (gameBoard[i][j] != player) { + break; + } + } + if (j == rows) { + return true; + } + + for (j = 0; j < rows; ++j) { + if (gameBoard[j][i] != player) { + break; + } + } + if (j == rows) { + return true; + } + } + + // Now check diagnols + for (i = 0; i < rows; ++i) { + if (gameBoard[i][i] != player) { + break; + } + } + + if (i == rows) { + return true; + } + + for (i = 0; i < rows; ++i) { + if (gameBoard[i][rows - i - 1] != player) { + break; + } + } + if (i == rows) { + return true; + } + + return false; +} + +function main() { + return new TicTacToe(); +} \ No newline at end of file diff --git a/games/tic-tac-toe-js/js/TicTacToeClient.js b/games/tic-tac-toe-js/js/TicTacToeClient.js new file mode 100644 index 0000000..444f921 --- /dev/null +++ b/games/tic-tac-toe-js/js/TicTacToeClient.js @@ -0,0 +1,92 @@ +// This first version doesn't take networking into account yet. + +function TicTacToeClient(container, server) { + this.server = server; + this.container = container; + this.init(); +} + + +TicTacToeClient.prototype.init = function() { + this.rows = 3; + this.spots = []; + this.myturn = false; + + var table = document.createElement("table"); + var tr = document.createElement("tr"); + var td = document.createElement("td"); + + var k = 0; + + for(var i=0; i < this.rows; i++) { + var atr = tr.cloneNode(true); + + for(var j=0; j < this.rows; j++) { + + var atd = td.cloneNode(true); + atd.id = + k++; + this.spots.push(atd); + + var self = this; + atd.onclick = function(e) { + self.move(e.target.id); + } + atr.appendChild(atd); + } + table.appendChild(atr); + } + + this.container.innerHTML = ""; + this.container.appendChild(table) + this.messages = document.createElement("ol"); + this.container.appendChild(this.messages); +} + +TicTacToeClient.prototype.move = function(id) { + var args = { + x: parseInt(id / this.rows), + y: parseInt(id) % this.rows + } + this.server.callCommand("tictactoe", this, "set", JSON.stringify(args)); +} + +TicTacToeClient.prototype.commandCalled = function(command, args) { + if (command == "world_set") { + var pars = JSON.parse(args); + if (pars["game_board"]) { + this.updateBoard(pars["game_board"]); + } + } else if (command == "yourturn") { + this.myturn = true; + } else if (command == "warning") { + this.addMessage(args); + } else if (command == "loser") { + this.addMessage(args); + } else if (command == "winner") { + this.addMessage(args); + } else throw "TTTC: Unnown command " + command; +} + +TicTacToeClient.prototype.addMessage = function(args) { + var message = document.createElement("li"); + message.innerHTML = args; + this.messages.appendChild(message) +} + +TicTacToeClient.prototype.updateBoard = function(gameBoardData) { + var k = 0; + for(var i=0; i + + + Tic Tac Toe - Player 1 + + + +

Tic Tac Toe and GGS simulation.

+
+

Player 1

+
+ + \ No newline at end of file diff --git a/games/tic-tac-toe-js/window2.html b/games/tic-tac-toe-js/window2.html new file mode 100644 index 0000000..754fec1 --- /dev/null +++ b/games/tic-tac-toe-js/window2.html @@ -0,0 +1,13 @@ + + + + Tic Tac Toe - Player 2 + + + +

Tic Tac Toe and GGS simulation.

+
+

Player 2

+
+ + \ No newline at end of file