aboutsummaryrefslogtreecommitdiff
path: root/gameserver/gameserver.html
diff options
context:
space:
mode:
Diffstat (limited to 'gameserver/gameserver.html')
-rw-r--r--gameserver/gameserver.html613
1 files changed, 613 insertions, 0 deletions
diff --git a/gameserver/gameserver.html b/gameserver/gameserver.html
new file mode 100644
index 0000000..d8528ab
--- /dev/null
+++ b/gameserver/gameserver.html
@@ -0,0 +1,613 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Game</title>
+<script>
+var S=5;
+var PLAYERS=["Player 1","Player 2"];
+var MOVES=[];
+
+var ws=null;
+var nick=null;
+var onturn=null;
+
+
+var moveidx=0;
+var neuidxhist=[];
+
+var board=Array.apply(null,new Array(S*S)).map(function(){return 0;});
+var fgcells=board.map(function(){return null;});
+var neuidx;
+
+var canclick=false;
+var isFirstMove=true;
+
+var imPlayer=-1;
+
+//var othermovefifo_interval=null;
+
+var clickenabled=[false,false];
+var input_neudir_choice=null,input_dir_choice=null,input_stone_choice=null;
+
+var hasInited=false,canAlreadyTurn=false;
+
+function preinit(){
+ ws=new WebSocket("ws://"+location.hostname+":8383");
+ ws.addEventListener("message",function(msg){
+ msg=msg.data;
+ var spaceidx=msg.indexOf(" "),
+ cmd=msg.slice(0,spaceidx),
+ arg=JSON.parse(msg.slice(spaceidx+1));
+ console.log(cmd,arg);
+ if(cmd=="nick"){
+ nick=arg;
+ document.getElementById("nickname").innerHTML=nick;
+ var choice=prompt("Your nickname is \""+nick+"\".\nEither you or your friend has to enter the other's nickname below; the other can press cancel or leave the field blank.");
+ if(!choice)return;
+ ws.send("game_create "+choice);
+ } else if(cmd=="game_create"){
+ if(arg==true){
+ ws.send("game_info");
+ imPlayer=1;
+ } else alert("ERROR:\n"+arg[1]);
+ } else if(cmd=="joined_game"){
+ ws.send("game_info");
+ imPlayer=2;
+ } else if(cmd=="game_info"){
+ if(arg==null){
+ alert("Not in a game!");
+ return;
+ }
+ PLAYERS=arg[0];
+ board=arg[1];
+ onturn=arg[2];
+ init(); //the magic call
+ hasInited=true;
+ if(canAlreadyTurn){
+ enableClicking(true,true);
+ isFirstMove=false;
+ canAlreadyTurn=false;
+ }
+ } else if(cmd=="game_doturn"){
+ if(arg[0]){
+ MOVES.push(arg[1]);
+ addmovelistrow(arg[1]);
+ nextmove();
+ } else alert(arg[1]);
+ } else if(cmd=="your_turn"){
+ canAlreadyTurn=true;
+ if(hasInited){
+ enableClicking(true,isFirstMove&&imPlayer==1);
+ isFirstMove=false;
+ }
+ if(arg){
+ MOVES.push(arg);
+ addmovelistrow(arg);
+ nextmove();
+ }
+ }
+ });
+ ws.addEventListener("open",function(){
+ ws.send("nick");
+ });
+}
+
+function init(){
+ var tr,td,y,x,e,span,
+ movelisttbody,
+ header=document.getElementById("header"),
+ status=document.getElementById("status"),
+ movelist=document.getElementById("movelist"),
+ bgtbody=document.getElementById("bgtbody");
+
+ document.title="Game: "+PLAYERS[0]+" vs "+PLAYERS[1];
+
+ header.appendChild(document.createTextNode("Game: "));
+ span=document.createElement("span");
+ span.classList.add("celltypeclr"); span.classList.add("celltypeclr_1");
+ span.appendChild(document.createTextNode(PLAYERS[0]));
+ header.appendChild(span);
+ header.appendChild(document.createTextNode(" vs "));
+ span=document.createElement("span");
+ span.classList.add("celltypeclr"); span.classList.add("celltypeclr_2");
+ span.appendChild(document.createTextNode(PLAYERS[1]));
+ header.appendChild(span);
+
+
+ e=document.createElement("table");
+ movelisttbody=document.createElement("tbody");
+ movelisttbody.id="movelisttbody";
+ tr=document.createElement("tr");
+ td=document.createElement("td"); td.innerHTML="Player"; tr.appendChild(td);
+ td=document.createElement("td"); td.innerHTML="Neutron"; tr.appendChild(td);
+ td=document.createElement("td"); td.innerHTML="Stone"; tr.appendChild(td);
+ movelisttbody.appendChild(tr);
+ e.appendChild(movelisttbody);
+ movelist.appendChild(e);
+
+ tr=document.createElement("tr");
+ td=document.createElement("td");
+ td.setAttribute("colspan","3");
+ td.innerHTML="&nbsp;";
+ tr.appendChild(td);
+ (function(tr){
+ tr.addEventListener("click",function(ev){
+ if(moveidx==0)return;
+ while(moveidx>0)prevmove(true);
+ setselectedmovelistline(0);
+ });
+ })(tr);
+ tr.classList.add("selected");
+ movelisttbody.appendChild(tr);
+
+ MOVES.forEach(function(mv,i){
+ addmovelistrow(mv,i);
+ });
+
+
+ var inputstonetbody=document.getElementById("inputstonetbody");
+ for(y=0;y<S;y++){
+ tr=document.createElement("tr");
+ for(x=0;x<S;x++){
+ td=document.createElement("td");
+ e=document.createElement("input");
+ e.setAttribute("type","radio");
+ e.setAttribute("name","inputstoneradio");
+ e.addEventListener("click",(function(x,y){return function(){
+ input_stone_choice=S*y+x;
+ };})(x,y));
+ td.appendChild(e);
+ tr.appendChild(td);
+ }
+ inputstonetbody.appendChild(tr);
+ }
+
+
+ for(y=0;y<S;y++){
+ tr=document.createElement("tr");
+ for(x=0;x<S;x++){
+ td=document.createElement("td");
+ td.classList.add("bgcell");
+ td.innerHTML=S*y+x;
+ tr.appendChild(td);
+ }
+ bgtbody.appendChild(tr);
+ }
+ for(x=0;x<S;x++){
+ board[x]=1;
+ e=makefgcell(x,1);
+ fgcells[x]=e;
+ document.body.appendChild(e);
+
+ board[S*(S-1)+x]=2;
+ e=makefgcell(S*(S-1)+x,2);
+ fgcells[S*(S-1)+x]=e;
+ document.body.appendChild(e);
+ }
+ neuidx=S*~~(S/2)+~~(S/2);
+ board[neuidx]=3;
+ e=makefgcell(neuidx,3);
+ fgcells[neuidx]=e;
+ document.body.appendChild(e);
+
+ setnextenabled(MOVES.length>0);
+ setprevenabled(false);
+ canclick=true;
+
+ /*othermovefifo_interval=setInterval(function(){
+ if(clickenabled[0]||clickenabled[1])return;
+ var xhr=new XMLHttpRequest();
+ xhr.addEventListener("readystatechange",function(){
+ if(this.readyState!=4)return;
+ console.log("othermove",this.status,this.responseText);
+ if(this.status!=200)return;
+ if(this.responseText=="go"){
+ enableClicking(true,true); //2nd true is to disable neutron dir
+ imPlayer=1;
+ } else if(this.responseText=="nogo"){
+ enableClicking(false);
+ imPlayer=2;
+ } else {
+ var mv=JSON.parse(this.responseText);
+ MOVES.push(mv);
+ addmovelistrow(mv);
+ nextmove();
+ enableClicking(true);
+ }
+ });
+ xhr.open("GET",location.protocol+"//"+location.host+"/othermove");
+ xhr.send();
+ },1500);*/
+
+ enableClicking(false);
+}
+
+function enableClicking(en,disneu){
+ var i,l;
+ en=en?true:false;
+ disneu=disneu?true:false;
+ for(i=0;i<8;i++){
+ document.getElementById("input_neudir"+i)[en&&!disneu?"removeAttribute":"setAttribute"]("disabled");
+ document.getElementById("input_dir"+i)[en?"removeAttribute":"setAttribute"]("disabled");
+ }
+ l=document.getElementsByName("inputstoneradio");
+ for(i=0;i<l.length;i++){
+ l[i][en&&(imPlayer==-1||board[i]==imPlayer)?"removeAttribute":"setAttribute"]("disabled");
+ }
+ document.getElementById("input_domovebtn")[en?"removeAttribute":"setAttribute"]("disabled");
+ clickenabled=[en,disneu];
+}
+
+function addmovelistrow(mv,i/*optional*/){
+ var tr,td;
+ var movelisttbody=document.getElementById("movelisttbody");
+ var i=i!=undefined?i:movelisttbody.children.length;
+ tr=document.createElement("tr");
+
+ td=document.createElement("td");
+ td.innerHTML=i%2+1;
+ tr.appendChild(td);
+
+ td=document.createElement("td");
+ if(mv[0]==-1)td.innerHTML="&nbsp;";
+ else td.innerHTML=arrowfor(mv[0]);
+ tr.appendChild(td);
+
+ td=document.createElement("td");
+ td.innerHTML=mv[1]+": "+arrowfor(mv[2]);
+ tr.appendChild(td);
+
+ tr.addEventListener("click",(function(target){return function(ev){
+ if(moveidx==target)return;
+ while(moveidx<target)nextmove(true);
+ while(moveidx>target)prevmove(true);
+ setselectedmovelistline(i+1);
+ };})(i+1));
+
+ movelisttbody.appendChild(tr);
+}
+
+function setselectedmovelistline(i){
+ var movelist=document.getElementById("movelist");
+ movelist.querySelectorAll("tr.selected")[0].classList.remove("selected");
+ document.getElementById("movelist").getElementsByTagName("tr")[i+1].classList.add("selected");
+}
+
+function arrowfor(dir){
+ return "&#x"+[2191,2197,2192,2198,2193,2199,2190,2196][dir]+";";
+}
+
+function bgcell(idx){
+ return document.getElementById("bgtbody").children[idx/S|0].children[idx%S];
+}
+function fgcellposition(idx){
+ var rect=bgcell(idx).getBoundingClientRect(),
+ scrolltop=window.pageYOffset||document.documentElement.scrollTop;
+ return [rect.left,rect.top+scrolltop];
+}
+function movefgcell(e,idx){
+ var pos=fgcellposition(idx);
+ e.style.left=pos[0]+"px";
+ e.style.top=pos[1]+"px";
+ e.cell_index=idx;
+}
+function makefgcell(idx,type){ //type in [1,2,3]
+ var pos=fgcellposition(idx),
+ e=document.createElement("div");
+ e.classList.add("fgcell");
+ e.classList.add("celltype_"+type);
+ e.setAttribute("style","left:"+pos[0]+"px;top:"+pos[1]+"px;");
+ e.cell_index=idx;
+ e.appendChild(document.createElement("div"));
+ return e;
+}
+
+var index_deltas=[[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1]];
+function indexafterslide(from,dir,overshoot){
+ var x=from%S,y=~~(from/S),x2,y2;
+ while(true){
+ x2=x+index_deltas[dir][0];
+ y2=y+index_deltas[dir][1];
+ if(x2<0||x2>=S||y2<0||y2>=S||board[S*y2+x2]!=0){
+ if(overshoot)return S*y2+x2;
+ else return S*y+x;
+ }
+ x=x2;
+ y=y2;
+ }
+}
+
+function setnextenabled(en){
+ document.getElementById("nextmovebtn").disabled=!en;
+}
+function setprevenabled(en){
+ document.getElementById("prevmovebtn").disabled=!en;
+}
+
+function nextmove(notimeout){
+ var newidx;
+ if(moveidx==MOVES.length||!canclick)return false;
+
+ if(MOVES[moveidx][0]!=-1){
+ neuidxhist.push(neuidx);
+ newidx=indexafterslide(neuidx,MOVES[moveidx][0]);
+ movefgcell(fgcells[neuidx],newidx);
+ board[newidx]=board[neuidx];
+ board[neuidx]=0;
+ fgcells[newidx]=fgcells[neuidx];
+ fgcells[neuidx]=null;
+ neuidx=newidx;
+
+ if(moveidx==MOVES.length-1)bgcell(neuidx).classList.add("win");
+ }
+
+ newidx=indexafterslide(MOVES[moveidx][1],MOVES[moveidx][2]);
+ if(MOVES[moveidx][0]!=-1&&!notimeout){
+ setTimeout(
+ (function(e,idx){return function(){
+ movefgcell(e,idx);
+ canclick=true;
+ };})(fgcells[MOVES[moveidx][1]],newidx),
+ 500
+ );
+ canclick=false;
+ } else {
+ movefgcell(fgcells[MOVES[moveidx][1]],newidx);
+ }
+ board[newidx]=board[MOVES[moveidx][1]];
+ board[MOVES[moveidx][1]]=0;
+ fgcells[newidx]=fgcells[MOVES[moveidx][1]];
+ fgcells[MOVES[moveidx][1]]=null;
+
+ moveidx++;
+ setprevenabled(true);
+ if(moveidx==MOVES.length)setnextenabled(false);
+ if(!notimeout)setselectedmovelistline(moveidx);
+ return true;
+}
+function prevmove(notimeout){
+ var item,oldneuidx,newidx,winGlowIdxToRemove=null;
+ if(moveidx==0||!canclick)return false;
+ moveidx--;
+
+ if(MOVES[moveidx][0]!=-1&&moveidx==MOVES.length-1)winGlowIdxToRemove=neuidx;
+
+ newidx=indexafterslide(MOVES[moveidx][1],MOVES[moveidx][2],true);
+ board[MOVES[moveidx][1]]=board[newidx];
+ board[newidx]=0;
+ fgcells[MOVES[moveidx][1]]=fgcells[newidx];
+ fgcells[newidx]=null;
+ movefgcell(fgcells[MOVES[moveidx][1]],MOVES[moveidx][1]);
+
+ if(MOVES[moveidx][0]!=-1){
+ oldneuidx=neuidxhist.pop();
+ board[oldneuidx]=board[neuidx];
+ board[neuidx]=0;
+ fgcells[oldneuidx]=fgcells[neuidx];
+ fgcells[neuidx]=null;
+ if(notimeout){
+ movefgcell(fgcells[oldneuidx],oldneuidx);
+ if(winGlowIdxToRemove!=null)bgcell(winGlowIdxToRemove).classList.remove("win");
+ } else {
+ setTimeout(
+ (function(e,idx){return function(){
+ movefgcell(e,idx);
+ canclick=true;
+ if(winGlowIdxToRemove!=null)bgcell(winGlowIdxToRemove).classList.remove("win");
+ };})(fgcells[oldneuidx],oldneuidx),
+ 500
+ );
+ canclick=false;
+ }
+ neuidx=oldneuidx;
+ }
+
+ setnextenabled(true);
+ if(moveidx==0)setprevenabled(false);
+ if(!notimeout)setselectedmovelistline(moveidx);
+ return true;
+}
+
+
+function input_neudir(dir){
+ var i;
+ for(i=0;i<8;i++){
+ if(i==dir)document.getElementById("input_neudir"+i).classList.add("selected");
+ else document.getElementById("input_neudir"+i).classList.remove("selected");
+ }
+}
+
+function input_dir(dir){
+ var i;
+ for(i=0;i<8;i++){
+ if(i==dir)document.getElementById("input_dir"+i).classList.add("selected");
+ else document.getElementById("input_dir"+i).classList.remove("selected");
+ }
+}
+
+function input_domove(){
+ var i,l,mv=[-1,-1,-1];
+ for(i=0;i<8;i++){
+ if(document.getElementById("input_neudir"+i).classList.contains("selected")){
+ mv[0]=i;
+ break;
+ }
+ }
+ for(i=0;i<8;i++){
+ if(document.getElementById("input_dir"+i).classList.contains("selected")){
+ mv[2]=i;
+ break;
+ }
+ }
+ l=document.getElementsByName("inputstoneradio");
+ for(i=0;i<l.length;i++){
+ if(l[i].checked){
+ mv[1]=i;
+ break;
+ }
+ }
+ if(mv[0]==-1&&!clickenabled[1]){alert("Neutron direction not set!");return;}
+ if(mv[1]==-1){alert("Stone choice not set!");return;}
+ if(mv[2]==-1){alert("Stone direction not set!");return;}
+ var clickenabledcache=clickenabled;
+ enableClicking(false);
+ /*var xhr=new XMLHttpRequest();
+ xhr.addEventListener("readystatechange",function(){
+ if(this.readyState!=4)return;
+ console.log("mynewmove",this.status,this.responseText);
+ if(this.status!=200){
+ alert("Failed to submit move!");
+ enableClicking.apply(this,clickenabledcache);
+ } else {
+ MOVES.push(mv);
+ addmovelistrow(mv);
+ nextmove();
+ }
+ });
+ xhr.open("POST",location.protocol+"//"+location.host+"/mynewmove");
+ xhr.send(JSON.stringify(mv));*/
+ ws.send("game_doturn "+mv.join(" "));
+}
+
+
+window.addEventListener("load",preinit,false);
+</script>
+<style>
+body{
+ font-family:Georgia,Times,Serif;
+ font-size:15px;
+}
+
+table#bgtab{
+ border-spacing:4px;
+}
+td.bgcell{
+ width:80px;
+ height:80px;
+ border:3px #ddd solid;
+ border-radius:12px;
+ transition:background-color 0.6s ease 0.2s, box-shadow 0.6s ease 0.2s, -webkit-box-shadow 0.6s ease 0.2s;
+
+ text-align:right;
+ vertical-align:bottom;
+ font-size:14px;
+}
+td.bgcell.win{
+ background-color:#8f8;
+ box-shadow:inset 0 0 6px #6e6;
+ -webkit-box-shadow:inset 0 0 6px #6e6;
+}
+div.fgcell{
+ position:absolute;
+ width:82px;
+ height:82px;
+ border:3px rgba(0,0,0,0) solid;
+ text-align:center;
+ transition:left 0.6s ease 0s, top 0.6s ease 0s;
+}
+
+div.fgcell > div{
+ height:75%;
+ margin:10px;
+ border-radius:30px;
+}
+
+h1#header{
+ letter-spacing:0.5px;
+}
+span.celltypeclr{
+ border-radius:5px;
+ padding:4px;
+}
+
+div#status{
+ font-size:16px;
+ font-weight:bold;
+}
+
+div.fgcell.celltype_1 > div{background-color:#ddd;}
+span.celltypeclr_1 {background-color:#ddd;}
+div.fgcell.celltype_2 > div{background-color:#2a2a2a;}
+span.celltypeclr_2 {background-color:#2a2a2a;color:#eee;}
+div.fgcell.celltype_3 > div{background-color:#11e;}
+
+div#movelist{
+ border:1px black solid;
+ width:500px;
+ height:200px;
+ overflow-y:scroll;
+}
+div#movelist table{
+ border-spacing:0;
+ width:100%;
+}
+div#movelist tr:first-child{
+ font-weight:bold;
+ background-color:#ccc;
+}
+div#movelist tr:first-child > td{
+ border-bottom:1px black solid;
+}
+div#movelist tr:nth-child(odd){background-color:#e4e4e4;}
+div#movelist tr:nth-child(even){background-color:#fff;}
+div#movelist tr:nth-child(n+2):hover{background-color:#bbf;cursor:pointer;}
+div#movelist tr.selected{
+ background-color:#afa;
+}
+
+input[type=button].selected{
+ background-color:#aaf;
+}
+</style>
+</head>
+<body>
+<h1 id="header"></h1>
+<table id="bgtab" style="display:inline-block"><tbody id="bgtbody"></tbody></table>
+<table id="inputneudirtab" style="display:inline-block"><tbody id="inputneudirtbody">
+ <tr>
+ <td><input type="button" id="input_neudir7" value="&#x2196;" onclick="input_neudir(7)"></td>
+ <td><input type="button" id="input_neudir0" value="&#x2191;" onclick="input_neudir(0)"></td>
+ <td><input type="button" id="input_neudir1" value="&#x2197;" onclick="input_neudir(1)"></td>
+ </tr>
+ <tr>
+ <td><input type="button" id="input_neudir6" value="&#x2190;" onclick="input_neudir(6)"></td>
+ <td>Neu</td>
+ <td><input type="button" id="input_neudir2" value="&#x2192;" onclick="input_neudir(2)"></td>
+ </tr>
+ <tr>
+ <td><input type="button" id="input_neudir5" value="&#x2199;" onclick="input_neudir(5)"></td>
+ <td><input type="button" id="input_neudir4" value="&#x2193;" onclick="input_neudir(4)"></td>
+ <td><input type="button" id="input_neudir3" value="&#x2198;" onclick="input_neudir(3)"></td>
+ </tr>
+</tbody></table>
+<table id="inputdirtab" style="display:inline-block;margin-left:20px"><tbody id="inputdirtbody">
+ <tr>
+ <td><input type="button" id="input_dir7" value="&#x2196;" onclick="input_dir(7)"></td>
+ <td style="text-align:center"><input type="button" id="input_dir0" value="&#x2191;" onclick="input_dir(0)"></td>
+ <td><input type="button" id="input_dir1" value="&#x2197;" onclick="input_dir(1)"></td>
+ </tr>
+ <tr>
+ <td><input type="button" id="input_dir6" value="&#x2190;" onclick="input_dir(6)"></td>
+ <td>
+ <table id="inputstonetab" style="display:inline-block"><tbody id="inputstonetbody"></tbody></table>
+ </td>
+ <td><input type="button" id="input_dir2" value="&#x2192;" onclick="input_dir(2)"></td>
+ </tr>
+ <tr>
+ <td><input type="button" id="input_dir5" value="&#x2199;" onclick="input_dir(5)"></td>
+ <td style="text-align:center"><input type="button" id="input_dir4" value="&#x2193;" onclick="input_dir(4)"></td>
+ <td><input type="button" id="input_dir3" value="&#x2198;" onclick="input_dir(3)"></td>
+ </tr>
+</tbody></table>
+<div style="display:inline-block;margin-left:10px">
+ <input type="button" id="input_domovebtn" value="Do move" onclick="input_domove()">
+ <br>
+</div>
+<br>
+<input type="button" id="prevmovebtn" onclick="prevmove()" value="&larr;">
+<input type="button" id="nextmovebtn" onclick="nextmove()" value="&rarr;"><br>
+<div id="movelist" style="margin-top:30px"></div>
+<div id="nickname"></div>
+</body>
+</html>