1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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();
});
|