summaryrefslogtreecommitdiff
path: root/botproxy.js
diff options
context:
space:
mode:
Diffstat (limited to 'botproxy.js')
-rwxr-xr-xbotproxy.js116
1 files changed, 116 insertions, 0 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();
+});