summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2018-02-20 10:49:59 +0100
committertomsmeding <tom.smeding@gmail.com>2018-02-20 10:49:59 +0100
commitb1b3cf82c0d0ccd6429145334c964e336858274a (patch)
treea207c7a31bf547c7c1fcd0e1823e467f606de65c
parent0afba2300e370f3567de784d2e9abda22084c652 (diff)
Botproxy
-rwxr-xr-xbotproxy.js116
-rw-r--r--package.json3
2 files changed, 118 insertions, 1 deletions
diff --git a/botproxy.js b/botproxy.js
new file mode 100755
index 0000000..1f64487
--- /dev/null
+++ b/botproxy.js
@@ -0,0 +1,116 @@
+#!/usr/bin/env node
+const io=require("socket.io-client");
+const child_process=require("child_process");
+
+let SERVER_URL=process.argv[3]?process.argv[3]:"http://localhost:15937";
+if(process.argv.length<3||process.argv.length>4){
+ console.log("Usage: ./botproxy.js <./bot> [http://server-url]");
+ process.exit(1);
+}
+const BOT_CMD=process.argv[2];
+
+function boardEmpty(bd){
+ for(const v of bd)if(v!=0)return false;
+ return true;
+}
+
+function boardDetectMove(prev,cur){
+ for(let i=0;i<prev.length;i++)if(prev[i]!=cur[i])return i;
+ return -1;
+}
+
+function encodeMove(idx,size){
+ return String.fromCharCode(65+idx%size)+(size-~~(idx/size));
+}
+
+function decodeMove(mv,size){
+ return size*(size-1-(mv.charCodeAt(1)-49))+mv.charCodeAt(0)-65;
+}
+
+function handleBotLine(line){
+ console.log(`PROXY: bot<- '${line.replace("\n","")}'`);
+ const idx=decodeMove(line,currentGame.size);
+ socket.emit("game_move",currentGame.id,idx);
+}
+
+let ME=null;
+let botproc=null;
+let currentGame=null;
+
+const socket=io(SERVER_URL);
+socket.on("connect",()=>{
+ socket.emit("my_info",(p)=>{
+ ME=p;
+ console.log(`PROXY: My name: '${ME.name}'`);
+ });
+});
+
+socket.on("err",(err)=>console.log(`ERROR: ${err}`));
+
+socket.on("game_create",(game)=>{
+ console.log(`PROXY: <- game_create ${JSON.stringify(game)}`);
+ if(game.size!=9){
+ console.log("PROXY: Invited for game with non-9 size!");
+ socket.emit("leave_game",game.id);
+ return;
+ }
+ currentGame=game;
+ botproc=child_process.spawn(BOT_CMD,{shell: true, stdio: ["pipe","pipe",process.stderr]});
+ let botbuf="";
+ botproc.stdout.on("data",(data)=>{
+ botbuf+=data.toString();
+ let idx=botbuf.indexOf("\n");
+ while(idx!=-1){
+ handleBotLine(botbuf.slice(0,idx));
+ botbuf=botbuf.slice(idx+1);
+ idx=botbuf.indexOf("\n");
+ }
+ });
+ botproc.stdout.on("end",()=>{
+ console.log("PROXY: Bot process exited!");
+ botproc.kill();
+ botproc=null;
+ if(currentGame)socket.emit("leave_game",currentGame.id);
+ socket.close();
+ });
+});
+
+socket.on("game_leave",(g,p)=>{
+ console.log(`PROXY: <- game_leave ${JSON.stringify(g)} ${JSON.stringify(p)}`);
+ if(g.id!=currentGame.id)return;
+ socket.emit("leave_game",g.id);
+ if(botproc)botproc.kill();
+ currentGame=null;
+});
+
+socket.on("game_turn",(g)=>{
+ console.log(`PROXY: <- game_turn ${JSON.stringify(g)}`);
+ if(g.id!=currentGame.id)return;
+ if(!botproc){
+ console.log("PROXY: game_turn while bot already died");
+ socket.emit("leave_game",g.id);
+ return;
+ }
+ const prevBoard=currentGame.board;
+ currentGame=g;
+ const mv=boardDetectMove(prevBoard,currentGame.board);
+ const towrite=mv==-1?"Start":encodeMove(mv,currentGame.size);
+ botproc.stdin.write(towrite+"\n");
+ console.log(`PROXY: ->bot '${towrite}'`);
+});
+
+socket.on("game_other_turn",(g)=>{
+ console.log(`PROXY: <- game_other_turn ${JSON.stringify(g)}`);
+ if(g.id!=currentGame.id)return;
+ currentGame=g;
+});
+
+socket.on("game_win",(g,p)=>{
+ console.log(`PROXY: <- game_win ${JSON.stringify(g)} ${JSON.stringify(p)}`);
+ if(g.id!=currentGame.id)return;
+ if(p.id==ME.id)console.log("PROXY: We won");
+ else console.log("PROXY: We lost");
+ socket.emit("leave_game",g.id);
+ if(botproc)botproc.kill();
+ socket.close();
+});
diff --git a/package.json b/package.json
index 564981d..6faf471 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"dependencies": {
"express": "^4.16.2",
"naampje": "^1.0.1",
- "socket.io": "^2.0.4"
+ "socket.io": "^2.0.4",
+ "socket.io-client": "^2.0.4"
}
}