#include #include #include #include #include #include #include #include "mm_help.h" int readline (int fd, char * buf, int len) { int ret, off=0; while (len > 1) { ret = read (fd, buf+off, len-1); if (ret < 0) { perror ("read"); exit (1); } if (ret == 0) { fprintf (stderr, "Unexpected EOF\n"); exit (1); } len -= ret; off += ret; if (buf[off-1] == '\n') { buf[off] = 0; assert (off >= 2 && buf[off-2] == '\r'); // fprintf (stderr, "READ: %s", buf); return 1; } } (*buf) = 0; return 0; } void writeline (int fd, char * buf) { int len = strlen (buf); int ret; // fprintf (stderr, "WRITE: %s", buf); assert (len >= 2 && buf[len-1] == '\n' && buf[len-2] == '\r'); while (len) { ret = write (fd, buf, len); if (ret < 0) { perror ("write"); exit (1); } buf += ret; len -= ret; } } int readreply (int fd, char * buf, int len) { int reply = -1, off = -1; if (!readline (fd, buf, len)) { fprintf (stderr, "Bad or incomplete line\n"); exit (1); } sscanf (buf, "%d %n", &reply, &off); if (reply < 100 || reply > 500 || off != 4) { fprintf (stderr, "Reply code missing or out of range\n"); exit (1); } return reply; } void parse_hello (char * buf, int * maxc, int * maxl) { int off=-1; sscanf (buf, "MMSERVER colmax=%d lenmax=%d\r\n%n", maxc, maxl, &off); if (off < 0 || buf[off]) { fprintf (stderr, "Badly formatted reply\n"); exit (1); } if ((*maxc) < 2 || (*maxl) < 2) { fprintf (stderr, "Bad maximum colour/length\n"); exit (1); } } void parse_bw (char * buf, int *b, int * w) { int off = -1; sscanf (buf, "Blacks=%d Whites=%d\r\n%n", b, w, &off); if (off < 0 || buf[off]) { fprintf (stderr, "Badly formatted reply\n"); exit (1); } if ((*b) < 0 || (*w) < 0) { fprintf (stderr, "Bad guess return from server\n"); exit (1); } } void reset(int * p) { int ret; static char buf[1000]; writeline (p[1], "RESET\r\n"); ret = readreply (p[0], buf, 1000); assert (ret == 203); } void doit (int * p, int c, int l) { int ng, done; static char buf[1000]; struct guess * guesses = NULL; guesses = get_guesses (c, l, 0); if (!guesses) { fprintf (stderr, "Too many posibilities for col=%d len=%d\n", c, l); reset (p); return; } ng = 0; done = 0; while (1) { int ret, b, w; struct guess *g; assert (guesses); sprintf (buf, "GUESS %s\r\n", guesses->g); writeline (p[1], buf); ng ++; ret = readreply (p[0], buf, 1000); if (ret == 205) { done = 1; break; } if (ret != 206) { fprintf (stderr, "Strange reply. Resetting\n"); break; } parse_bw (buf+4, &b, &w); g = guesses; while (g->next) { int tb, tw; bw (guesses->g, g->next->g, &tb, &tw); if (tb != b || tw != w) { struct guess * tmp = g->next; g->next = tmp->next; free (tmp); } else { g = g->next; } } g = guesses; guesses = g->next; free (g); } while (guesses) { struct guess * g; g = guesses; guesses = g->next; free (g); } if (done) { printf ("Solved cols=%d len=%d after %d guesses\n", c, l, ng); } } int main () { static char buf[1000]; int ret; int maxc, maxl; int l, c; int p[2]; p[0] = open ("p2", O_RDONLY); if (p[0] < 0) { perror ("open"); exit (1); } p[1] = open ("p1", O_WRONLY); if (p[1] < 0) { perror ("open"); exit (1); } ret = readreply (p[0], buf, 1000); assert (ret == 200); parse_hello (buf+4, &maxc, &maxl); for (l=3; l<10; l++) { for (c=3; c<10; c++) { sprintf (buf, "game FREE %d %d\r\n", c, l); writeline (p[1], buf); ret = readreply (p[0], buf, 1000); switch (ret) { case 500: case 501: fprintf (stderr, "col=%d len=%d not supported\n", c, l); break; case 201: doit (p,c,l); break; default: fprintf (stderr, "Ooops. Resetting connection\n"); reset (p); break; } } } writeline (p[1], "quit\r\n"); ret = readreply (p[0], buf, 1000); assert (ret == 207); return 0; }