html5-RockPaperScissors

RockPaperScissors on WebSocket

main

contrib/rockPaperScissors/main.js
  • explaination on the game http://en.wikipedia.org/wiki/Rock-paper-scissors

  • fix the connection establishmenet. this is like a tcp connection establishement

    • with a simulteneous open case which is super frequent
    • http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-3.htm
    • http://www.tcpipguide.com/free/t_TCPConnectionEstablishmentProcessTheThreeWayHandsh-4.htm
  • display a nice log of current game events
    • thus it is easier to diagnose the issues

Define the namespace

var Rockps	= {}

Rockps.Move defines the various moves

Rockps.Move		= function(value){
	this.value	= value;
};

Rockps.Move.NONE	= "none";
Rockps.Move.ROCK	= "rock";
Rockps.Move.SCISSORS	= "scissors";
Rockps.Move.PAPER	= "paper";

Rockps.Move.getRandom	= function(){
	var moves	= [Rockps.Move.ROCK, Rockps.Move.SCISSORS, Rockps.Move.PAPER];
	var idx		= Math.floor(Math.random() * moves.length)
	return new Rockps.Move(moves[idx]);
}
Rockps.Move.prototype.imageUrl	= function(){
	var imageUrls	= {
		"rock"		: "image/rock.png",
		"paper"		: "image/paper.png",
		"scissors"	: "image/scissors.png"
	}
	console.assert(this.isFromPlayer())
	return imageUrls[this.value];
}

Display an <img> of a given move in a container

Rockps.Move.prototype.display	= function(container){
	jQuery(&quot;&lt;img&gt;&quot;)
		.attr('width', 128)
		.attr('height', 128)
		.attr(&quot;src&quot;, this.imageUrl())
		.replaceAll(container);	
}

  • return: Boolean true if the move may be from a player, false otherwise
Rockps.Move.prototype.isFromPlayer= function(move){
	return [Rockps.Move.ROCK, Rockps.Move.SCISSORS, Rockps.Move.PAPER].indexOf(this.value) != -1;
}

Decide the result of the game based on player moves

  • returns: Rockps.Result return the result for the first player
Rockps.Move.prototype.decideResult	= function(otherMove){
	var moveCmpGt	= function(myMove, otherMove){
		var MOVE	= Rockps.Move;
		if( myMove === MOVE.ROCK	&amp;&amp; otherMove === MOVE.SCISSORS)	return true;
		if( myMove === MOVE.SCISSORS	&amp;&amp; otherMove === MOVE.PAPER )	return true;
		if( myMove === MOVE.PAPER	&amp;&amp; otherMove === MOVE.ROCK )	return true;
		return false;		
	}
	if( moveCmpGt(this.value, otherMove.value) )	return new Rockps.Result(Rockps.Result.WIN);
	if( moveCmpGt(otherMove.value, this.value) )	return new Rockps.Result(Rockps.Result.LOSS);
	return new Rockps.Result(Rockps.Result.DRAW);
}
Rockps.Result		= function(value){
	this.value	= value;
};

Rockps.Result defines the possible game results

Rockps.Result.NONE	= &quot;none&quot;;
Rockps.Result.WIN	= &quot;win&quot;;
Rockps.Result.DRAW	= &quot;draw&quot;;
Rockps.Result.LOSS	= &quot;loss&quot;;

Rockps.Result.prototype.display	= function(container){
	var texts	= {
		&quot;win&quot;	: &quot;You Won!! congratulation&quot;,
		&quot;draw&quot;	: &quot;Draw. great minds meet each other&quot;,
		&quot;loss&quot;	: &quot;You lose... Better luck next time ?&quot;
	}
	jQuery(&quot;&lt;p&gt;&quot;)
		.text(texts[this.value])
		.appendTo(jQuery(container).empty());		
}

Rockps.Result defines the possible game results

Rockps.MESSAGE			= {};
Rockps.MESSAGE.NONE		= &quot;none&quot;;
Rockps.MESSAGE.HELLO_SYN	= &quot;hello_syn&quot;;
Rockps.MESSAGE.HELLO_ACK	= &quot;hello_ack&quot;;
Rockps.MESSAGE.HELLO_SYNACK	= &quot;hello_synack&quot;;
Rockps.MESSAGE.PLY		= &quot;ply&quot;;

Define the game class

Rockps.Game		= function(){
	var curState	= Rockps.Game.STATE.NONE;
	var username	= &quot;user-&quot;+Math.floor(Math.random() * 1000000).toString(32);
	var otherUserName= null;
	var myMove	= Rockps.Move.getRandom();
	
console.log(&quot;myMove&quot;, myMove);
(function(){
	var localMove	= Rockps.Move.getRandom();
	var remoteMove	= Rockps.Move.getRandom();
	var result	= localMove.decideResult(remoteMove);
	// display everything
	localMove	.display(&quot;.content .playerContainer.localPlayer .move&quot;);
	remoteMove	.display(&quot;.content .playerContainer.remotePlayer .move&quot;);
	result		.display(&quot;.content .resultContainer&quot;);
})();
 * Initialise the websocket
var socket	= new EasyWebSocket(&quot;ws://easywebsocket.org/html5-rockpaperscissors");
	socket.onopen	= function() {
		console.log(&quot;Connnected to&quot;, this.url, this)
		socket.send(JSON.stringify({
			type	: Rockps.MESSAGE.HELLO_SYN,
			data	: {
				srcUserName	: username
			}
		}))	
	}
	socket.onmessage = function(event) {
		var message	= JSON.parse(event.data)
		console.assert(typeof(message.type) != &quot;undefined&quot;);
		console.assert(typeof(message.data) != &quot;undefined&quot;);
		// ignore messages from myself
		if( message.data.srcUserName == username )	return;
		// log the event
		console.log(&quot;message&quot;, &quot;type&quot;, message.type, &quot;data&quot;, message.data)
		// parse according to message.type
		if( message.type == Rockps.MESSAGE.HELLO_SYN ){
			// answer by a HELLO_ACK
			socket.send(JSON.stringify({
				type	: Rockps.MESSAGE.HELLO_ACK,
				data	: {
					srcUserName	: username,
					dstUserName	: message.data.srcUserName,
					room		: &quot;room-&quot;+Math.floor(Math.random() * 1000000).toString(32)
				}
			}))
		}else if( message.type == Rockps.MESSAGE.HELLO_ACK ){
			var otherUserName	= message.data.srcUserName
			// ignore message who arent from myself
			if( message.data.dstUserName != username )	return;
			// reply to this message
			socket.send(JSON.stringify({
				type	: Rockps.MESSAGE.HELLO_SYNACK,
				data	: {
					srcUserName	: username,
					dstUserName	: message.data.srcUserName,
					room		: message.data.room
				}
			}))
		}else if( message.type == Rockps.MESSAGE.HELLO_SYNACK ){
			
		}else if( message.type == Rockps.MESSAGE.PLY ){
			// ignore message who arent from myself
			if( message.data.dstUserName != username )	return;
			// log the event
			console.log(&quot;Your move is &quot;, myMove)
			console.log(&quot;opponent is &quot;, message.data.srcUserName,&quot; and its move is&quot;, message.data.srcMove)
			// compute the result
			var result	= Rockps.Move.decideResult(myMove, message.data.srcMove);
			if( result == Rockps.Result.WIN ){
				console.log(&quot;Congrats you win against&quot;, message.data.srcUserName)
			}else if( result == Rockps.Result.LOSS ){
				console.log(&quot;Unfortunatly you lost against&quot;, message.data.srcUserName)
			}else if( result == Rockps.Result.DRAW ){
				console.log(&quot;This is a draw against&quot;, message.data.srcUserName)
			}else console.assert(false);
		}
	}

}

Describe the possible STATE of a Rockps.Game

Rockps.Game.STATE		= {};
Rockps.Game.STATE.NONE		= &quot;none&quot;;
Rockps.Game.STATE.FINDOPPONENT	= &quot;findopponent&quot;;
Rockps.Game.STATE.PLAYING	= &quot;playing&quot;;


	

jQuery(function(){
	// some global init 
	EasyWebSocket.iframeOrigin	= &quot;http://localhost:8080";
	//EasyWebSocket.logFunction	= function(){ console.log.apply(console, arguments) };

	var game	= new Rockps.Game();	
});