#!/usr/bin/env node var aicmd; if(process.argv.length!=3){ console.log("Give AI command to run as command line argument."); process.exit(1); } aicmd=process.argv[2]; console.log("Using AI command '"+aicmd+"'"); var app=require("express")(), http=require("http").Server(app), io=require("socket.io")(http), fs=require("fs"), spawn=require("child_process").spawn; eval(String(fs.readFileSync("common.js"))); var HTTPPORT=8080; var uniqid=(function(){ var id=0; return function(){return id++;}; })(); app.get("/",function(req,res){ res.sendFile(__dirname+"/index.html"); }); ["index.html","common.js"].forEach(function(fname){ app.get("/"+fname,function(req,res){ res.sendFile(__dirname+"/"+fname); }); }); function stopproc(proc){ proc.stdin.write("Quit\n"); var timeout=setTimeout(function(){ proc.kill(); },500); proc.on("exit",function(){ clearTimeout(timeout); }); } io.on("connection",function(conn){ var id=uniqid(); console.log("New IO connection id "+id); var bd=emptyboard(); var aiplayer=0; conn.on("disconnect",function(){ console.log("Disconnect id "+id); }); conn.on("usermove",function(idx){ idx=+idx; if(idx<0||idx>=W*H){ conn.emit("alert","You sent an invalid move, index "+idx); conn.emit("getusermove"); return; } var x=idx%W,y=~~(idx/W); bd[y][x].c=1-aiplayer; bd[y][x].n++; bd=stabilise(bd); if(countballs(bd)>2){ var win=checkwin(bd); if(win!=-1){ conn.emit("win",1-aiplayer); stopproc(proc); return; } } proc.stdin.write(x+" "+y+"\n"); conn.emit("setonturn",aiplayer); }); var proc=spawn("sh",["-c",aicmd],{ stdio:["pipe","pipe",process.stderr] }); var buffer=""; proc.stdout.on("data",function(data){ var idx,line,mv,win; buffer+=data; while((idx=buffer.indexOf("\n"))!=-1){ line=buffer.slice(0,idx); buffer=buffer.slice(idx+1); mv=line.split(" ").map(function(s){return parseInt(s,10);}); if(mv.length!=2||isNaN(mv[0])||isNaN(mv[1])){ console.log("Invalid move written by AI: '"+line+"'"); conn.emit("alert","Invalid move written by AI: '"+line+"'"); mv[0]=0; mv[1]=0; } bd[mv[1]][mv[0]].c=aiplayer; bd[mv[1]][mv[0]].n++; bd=stabilise(bd); conn.emit("applymove",{index:W*mv[1]+mv[0],player:aiplayer}); if(countballs(bd)>2){ win=checkwin(bd); if(win!=-1){ conn.emit("win",aiplayer); stopproc(proc); return; } } conn.emit("setonturn",1-aiplayer); conn.emit("getusermove"); } }); proc.stdin.write("A\n-1 -1\n"); conn.emit("emptyboard"); conn.emit("setonturn",0); }); http.listen(HTTPPORT,function(){ console.log("Listening on http://localhost:"+HTTPPORT); });