diff options
Diffstat (limited to 'gameserver/gameserver.html')
-rw-r--r-- | gameserver/gameserver.html | 613 |
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=" "; + 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=" "; + 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="↖" onclick="input_neudir(7)"></td> + <td><input type="button" id="input_neudir0" value="↑" onclick="input_neudir(0)"></td> + <td><input type="button" id="input_neudir1" value="↗" onclick="input_neudir(1)"></td> + </tr> + <tr> + <td><input type="button" id="input_neudir6" value="←" onclick="input_neudir(6)"></td> + <td>Neu</td> + <td><input type="button" id="input_neudir2" value="→" onclick="input_neudir(2)"></td> + </tr> + <tr> + <td><input type="button" id="input_neudir5" value="↙" onclick="input_neudir(5)"></td> + <td><input type="button" id="input_neudir4" value="↓" onclick="input_neudir(4)"></td> + <td><input type="button" id="input_neudir3" value="↘" 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="↖" onclick="input_dir(7)"></td> + <td style="text-align:center"><input type="button" id="input_dir0" value="↑" onclick="input_dir(0)"></td> + <td><input type="button" id="input_dir1" value="↗" onclick="input_dir(1)"></td> + </tr> + <tr> + <td><input type="button" id="input_dir6" value="←" 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="→" onclick="input_dir(2)"></td> + </tr> + <tr> + <td><input type="button" id="input_dir5" value="↙" onclick="input_dir(5)"></td> + <td style="text-align:center"><input type="button" id="input_dir4" value="↓" onclick="input_dir(4)"></td> + <td><input type="button" id="input_dir3" value="↘" 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="←"> +<input type="button" id="nextmovebtn" onclick="nextmove()" value="→"><br> +<div id="movelist" style="margin-top:30px"></div> +<div id="nickname"></div> +</body> +</html> |