diff options
Diffstat (limited to 'humanbot.cpp')
-rw-r--r-- | humanbot.cpp | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/humanbot.cpp b/humanbot.cpp new file mode 100644 index 0000000..5902e24 --- /dev/null +++ b/humanbot.cpp @@ -0,0 +1,254 @@ +#include <iostream> +#include <fstream> +#include <sstream> +#include <vector> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cassert> +#include <unistd.h> +#include <signal.h> +#include <sys/time.h> +#include <sys/stat.h> + +#define S (5) + +using namespace std; + +bool should_flip_board=false; + +struct Move; +class Board; + +Move protocol_get_move(istream &s); +void protocol_put_move(ostream &s,Move m); + +int index_deltas[8][2]={{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; + +struct Move{ + int neudir,from,dir; + string str(void){ + stringstream ss; + ss<<neudir<<' '<<from<<' '<<dir; + return ss.str(); + } +}; + +class Board{ +public: + int grid[S*S]; + int neuidx; + Board(void):neuidx(S*(S/2)+S/2){ + memset(grid,0,S*S*sizeof(int)); + grid[S*(S/2)+S/2]=3; + for(int i=0;i<S;i++){ + grid[i]=1; + grid[S*(S-1)+i]=2; + } + } + int moved(int at,int dir){ + int x=at%S,y=at/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||grid[S*y2+x2]!=0)return S*y+x; + x=x2; + y=y2; + } + } + bool move(int at,int dir){ + int newat=moved(at,dir); + if(newat==at)return false; + grid[newat]=grid[at]; + grid[at]=0; + if(grid[newat]==3)neuidx=newat; + return true; + } + void undomove(int at,int dir){ + int movedidx=moved(at,dir); + movedidx+=S*index_deltas[dir][1]+index_deltas[dir][0]; + grid[at]=grid[movedidx]; + grid[movedidx]=0; + if(grid[at]==3)neuidx=at; + } + bool isvalid(Move mv){ + int oldneuidx=neuidx; + //cerr<<"Called isvalid with move "; + //protocol_put_move(cerr,mv); + //print(); + if(!move(oldneuidx,mv.neudir)){ + //undomove(oldneuidx,mv.neudir); + return false; + } + if(!move(mv.from,mv.dir)){ + //undomove(mv.from,mv.dir); + undomove(oldneuidx,mv.neudir); + return false; + } + undomove(mv.from,mv.dir); + undomove(oldneuidx,mv.neudir); + return true; + } + void print(void){ + int x,y; + if(should_flip_board){ + for(y=S-1;y>=0;y--){ + for(x=S-1;x>=0;x--)cerr<<grid[S*y+x]<<' '; + cerr<<endl; + } + } else { + for(y=0;y<S;y++){ + for(x=0;x<S;x++)cerr<<grid[S*y+x]<<' '; + cerr<<endl; + } + } + } +}; + + +void restart_server(void); +void kill_server(void); + +ofstream othermovefifo; +ifstream mynewmovefifo; + +Move calculate_move(Board &bd){ + cerr<<"c_m: restarting server..."<<endl; + restart_server(); + cerr<<"c_m: Waiting for move from fifo..."<<endl; + Move mv=protocol_get_move(mynewmovefifo); + cerr<<"c_m: Got move from fifo."<<endl; + return mv; +} + +long server_pid=-1; +int server_port=-1; + +void setup_server(void){ + unlink(".humanbot__.__othermove.fifo"); + assert(mkfifo(".humanbot__.__othermove.fifo",0666)==0); + + unlink(".humanbot__.__mynewmove.fifo"); + assert(mkfifo(".humanbot__.__mynewmove.fifo",0666)==0); + + server_port=42000+rand()%1000; + + restart_server(); + + //only now can we do this, 'cause unix doesn't let a fifo exist with only one end + othermovefifo.open(".humanbot__.__othermove.fifo",ofstream::out|ofstream::app); + mynewmovefifo.open(".humanbot__.__mynewmove.fifo"); + cerr<<"Opened fifo's!"<<endl; +} + +void restart_server(void){ + if(server_pid!=-1)kill_server(); + pid_t cpid=fork(); + assert(cpid!=-1); + if(cpid==0){ //child + cerr<<"Child!"<<endl; + server_pid=(long)getpid(); + char *portstr; + asprintf(&portstr,"%d",server_port); + assert(!!portstr); + execl("/usr/bin/env","node","./humanbot_server.js",portstr,NULL); + perror("execlp"); + exit(1); + } + cerr<<"Parent!"<<endl; +} + +void kill_server(void){ + kill(server_pid,SIGTERM); //stay friendly + usleep(100*1000); //100ms + kill(server_pid,SIGINT); + usleep(1000*1000); //1s +} + + +inline int flip_index(int idx){ + return S*(S-1-idx/S)+S-1-idx%S; +} +inline int flip_dir(int dir){ + return dir==-1?-1:(dir+4)%8; +} + +Move protocol_get_move(istream &s){ + Move m; + /*char c=s.peek(); + if(c=='q'||c=='Q')exit(0);*/ + cerr<<"Sleeping."<<endl; + system("sleep 10"); + s>>m.neudir>>m.from>>m.dir; + if(should_flip_board){ + m.neudir=flip_dir(m.neudir); + m.from=flip_index(m.from); + m.dir=flip_dir(m.dir); + } + cerr<<"Got: "; + protocol_put_move(cerr,m); + s.ignore(1024,'\n'); + return m; +} + +void protocol_put_move(ostream &s,Move m){ + if(should_flip_board){ + s<<flip_dir(m.neudir)<<' '<<flip_index(m.from)<<' '<<flip_dir(m.dir)<<endl; + } else { + s<<m.neudir<<' '<<m.from<<' '<<m.dir<<endl; + } +} + +int main(void){ + Board bd; + Move mv; + string line; + struct timeval tv; + gettimeofday(&tv,NULL); + cerr<<"seed="<<(1000000*tv.tv_sec+tv.tv_usec)<<endl; + srand(1000000*tv.tv_sec+tv.tv_usec); + //srand(1430130052185291); + setup_server(); + getline(cin,line); + if(line=="go"){ + othermovefifo<<"go"<<endl; + should_flip_board=false; + //mv.neudir=-1; mv.from=1; mv.dir=3; + mv=calculate_move(bd); + bd.move(mv.from,mv.dir); + protocol_put_move(cout,mv); + } else { + if(line!="nogo")cerr<<"no0b "<<line<<" not in (go,nogo)"<<endl; + othermovefifo<<"nogo"<<endl; + should_flip_board=true; + mv=protocol_get_move(cin); + protocol_put_move(othermovefifo,mv); + bd.move(mv.from,mv.dir); + bd.print(); + mv=calculate_move(bd); + if(!bd.isvalid(mv)){ + cerr<<"calculate_move gave invalid move "<<mv.str()<<endl; + return 1; + } + bd.move(bd.neuidx,mv.neudir); + bd.move(mv.from,mv.dir); + protocol_put_move(cout,mv); + } + while(true){ + bd.print(); + mv=protocol_get_move(cin); + protocol_put_move(othermovefifo,mv); + bd.move(bd.neuidx,mv.neudir); + bd.move(mv.from,mv.dir); + bd.print(); + mv=calculate_move(bd); + if(!bd.isvalid(mv)){ + cerr<<"calculate_move gave invalid move "<<mv.str()<<endl; + return 1; + } + bd.move(bd.neuidx,mv.neudir); + bd.move(mv.from,mv.dir); + protocol_put_move(cout,mv); + } + return 0; +} |