aboutsummaryrefslogtreecommitdiff
path: root/humanbot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'humanbot.cpp')
-rw-r--r--humanbot.cpp254
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;
+}