Updated help commands to only display allowed subset in two player mode.
[sgk-go] / interface / play_twoplayer.c
index e809cbf..3008925 100644 (file)
 #include "gnugo.h"
 
 #include <ctype.h>
 #include "gnugo.h"
 
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define _XOPEN_SOURCE 500
 
 #if READLINE
 #include <readline/history.h>
 
 #if READLINE
 #include <readline/history.h>
 #include "sgftree.h"
 
 #define DEBUG_COMMANDS "\
 #include "sgftree.h"
 
 #define DEBUG_COMMANDS "\
-capture <pos>    try to capture indicated group\n\
-dead             Toggle display of dead stones\n\
-defend <pos>     try to defend indicated group\n\
-listdragons      print dragon info \n\
-showarea         display area\n\
-showdragons      display dragons\n\
-showmoyo         display moyo\n\
-showterri        display territory\n\
+No debug commands in two player mode\n\
 "
 
 "
 
+#define MASTER_FIFO_NAME "/tmp/sgkgo-fifo-master"
+#define SLAVE_FIFO_NAME  "/tmp/sgkgo-fifo-slave"
+
 /* ANSI color codes */
 #define RESETCOLOR "\x1B[0m"
 #define WHITECOLOR "\x1B[41m"
 /* ANSI color codes */
 #define RESETCOLOR "\x1B[0m"
 #define WHITECOLOR "\x1B[41m"
@@ -71,13 +73,13 @@ static int clock_on = 0;
 /* Keep track of the score estimated before the last computer move. */
 static int current_score_estimate = NO_SCORE;
 
 /* Keep track of the score estimated before the last computer move. */
 static int current_score_estimate = NO_SCORE;
 
-static void do_play_twoplayer(Gameinfo* gameinfo);
+static void do_play_twoplayer(Gameinfo* gameinfo, int transmit_fifo_fd, int receive_fifo_fd);
 static int twoplayer_endgame(Gameinfo* gameinfo, int reason);
 static void twoplayer_count(Gameinfo* gameinfo);
 static int twoplayer_endgame(Gameinfo* gameinfo, int reason);
 static void twoplayer_count(Gameinfo* gameinfo);
-static void showcapture(char* line);
-static void showdefense(char* line);
-static void twoplayer_goto(Gameinfo* gameinfo, char* line);
-static void twoplayer_free_handicap(Gameinfo* gameinfo, char* handicap_string);
+//static void showcapture(char* line);
+//static void showdefense(char* line);
+//static void twoplayer_goto(Gameinfo* gameinfo, char* line);
+//static void twoplayer_free_handicap(Gameinfo* gameinfo, char* handicap_string);
 
 /* If sgf game info is written can't reset parameters like handicap, etc. */
 static int sgf_initialized;
 
 /* If sgf game info is written can't reset parameters like handicap, etc. */
 static int sgf_initialized;
@@ -320,36 +322,19 @@ static void
 show_commands(void)
 {
     printf("\nCommands:\n");
 show_commands(void)
 {
     printf("\nCommands:\n");
-    printf(" back                Take back your last move\n");
-    printf(" boardsize           Set boardsize (on move 1 only)\n");
     printf(" comment             Write a comment to outputfile\n");
     printf(" depth <num>         Set depth for reading\n");
     printf(" display             Display game board\n");
     printf(" exit                Exit GNU Go\n");
     printf(" comment             Write a comment to outputfile\n");
     printf(" depth <num>         Set depth for reading\n");
     printf(" display             Display game board\n");
     printf(" exit                Exit GNU Go\n");
-    printf(" force <move>        Force a move for current color\n");
-    printf(" forward             Go to next node in game tree\n");
-    printf(" goto <movenum>      Go to movenum in game tree\n");
     printf(" level <amount>      Playing level (default = 10)\n");
     printf(" level <amount>      Playing level (default = 10)\n");
-    printf(" handicap <num>      Set fixed handicap (on move 1 only)\n");
-    printf(" freehandicap <num>  Place free handicap (on move 1 only)\n");
-    printf("                     Omit <num> to place handicap yourself\n");
     printf(" help                Display this help menu\n");
     printf(" helpdebug           Display debug help menu\n");
     printf(" info                Display program settings\n");
     printf(" help                Display this help menu\n");
     printf(" helpdebug           Display debug help menu\n");
     printf(" info                Display program settings\n");
-    printf(" komi                Set komi (on move 1 only)\n");
-    printf(" last                Goto last node in game tree\n");
     printf(" pass                Pass on your move\n");
     printf(" pass                Pass on your move\n");
-    printf(" play <num>          Play <num> moves\n");
-    printf(" playblack           Play as Black (switch if White)\n");
-    printf(" playwhite           Play as White (switch if Black)\n");
     printf(" quit                Exit GNU Go\n");
     printf(" quit                Exit GNU Go\n");
-    printf(" resign              Resign the current game\n");
     printf(" save <file>         Save the current game\n");
     printf(" save <file>         Save the current game\n");
-    printf(" load <file>         Load a game from file\n");
     printf(" score               Toggle display of score On/Off\n");
     printf(" showboard           Toggle display of board On/Off\n");
     printf(" score               Toggle display of score On/Off\n");
     printf(" showboard           Toggle display of board On/Off\n");
-    printf(" switch              Switch the color you are playing\n");
-    printf(" undo                Take the last move back (same as back)\n");
     printf(" <move>              A move of the format <letter><number>");
     printf("\n");
 }
     printf(" <move>              A move of the format <letter><number>");
     printf("\n");
 }
@@ -530,34 +515,51 @@ init_sgf(Gameinfo* ginfo)
         sgffile_recordboard(sgftree.root);
 }
 
         sgffile_recordboard(sgftree.root);
 }
 
+/*
+ * Communication with second player.
+ */
+
+static int
+twoplayer_recv_move(int fd)
+{
+    int move;
+    printf("\nWaiting to receive move from other player...\n");
+    if (read(fd, &move, sizeof(move)) != sizeof(int)) {
+        printf("\n");
+        printf(WHITECOLOR "                                                       " RESETCOLOR);
+        printf("\n");
+        printf(WHITECOLOR " " RESETCOLOR);
+        printf("Unrecoverable error. Save game if desired, then quit.");
+        printf(WHITECOLOR " " RESETCOLOR);
+        printf("\n");
+        printf(WHITECOLOR "                                                       " RESETCOLOR);
+        printf("\n");
+        printf("\n");
+        move = NO_MOVE;
+    }
+    return move;
+}
+
+static void
+twoplayer_send_move(int move, int fd)
+{
+    write(fd, &move, sizeof(move));
+}
+
 /*
  * Generate the computer move. 
  */
 
 static int
 /*
  * Generate the computer move. 
  */
 
 static int
-computer_move(Gameinfo* gameinfo, int* passes)
+computer_move(Gameinfo* gameinfo, int* passes, int receive_fifo_fd)
 {
     int move;
 {
     int move;
-    float move_value;
-    int resign;
     int resignation_declined = 0;
     float upper_bound, lower_bound;
 
     init_sgf(gameinfo);
 
     int resignation_declined = 0;
     float upper_bound, lower_bound;
 
     init_sgf(gameinfo);
 
-    /* Generate computer move. */
-    if (autolevel_on)
-        adjust_level_offset(gameinfo->to_move);
-    move = genmove(gameinfo->to_move, &move_value, &resign);
-    if (resignation_allowed && resign) {
-        int state = twoplayer_endgame(gameinfo, 2);
-        if (state != -1)
-            return state;
-
-        /* The opponent declined resignation. Remember not to resign again. */
-        resignation_allowed = 0;
-        resignation_declined = 1;
-    }
+    move = twoplayer_recv_move(receive_fifo_fd);
 
     if (showscore) {
         gnugo_estimate_score(&upper_bound, &lower_bound);
 
     if (showscore) {
         gnugo_estimate_score(&upper_bound, &lower_bound);
@@ -572,7 +574,6 @@ computer_move(Gameinfo* gameinfo, int* passes)
         *passes = 0;
 
     gnugo_play_move(move, gameinfo->to_move);
         *passes = 0;
 
     gnugo_play_move(move, gameinfo->to_move);
-    sgffile_add_debuginfo(sgftree.lastnode, move_value);
     sgftreeAddPlay(&sgftree, gameinfo->to_move, I(move), J(move));
     if (resignation_declined)
         sgftreeAddComment(&sgftree, "GNU Go resignation was declined");
     sgftreeAddPlay(&sgftree, gameinfo->to_move, I(move), J(move));
     if (resignation_declined)
         sgftreeAddComment(&sgftree, "GNU Go resignation was declined");
@@ -587,7 +588,8 @@ computer_move(Gameinfo* gameinfo, int* passes)
  */
 
 static int
  */
 
 static int
-do_move(Gameinfo* gameinfo, char* command, int* passes, int force)
+do_move(Gameinfo* gameinfo, char* command, int* passes, int force,
+        int transmit_fifo_fd, int receive_fifo_fd)
 {
     int move = string_to_location(board_size, command);
 
 {
     int move = string_to_location(board_size, command);
 
@@ -601,6 +603,8 @@ do_move(Gameinfo* gameinfo, char* command, int* passes, int force)
         return 0;
     }
 
         return 0;
     }
 
+    twoplayer_send_move(move,transmit_fifo_fd);
+
     *passes = 0;
     TRACE("\nyour move: %1m\n\n", move);
     init_sgf(gameinfo);
     *passes = 0;
     TRACE("\nyour move: %1m\n\n", move);
     init_sgf(gameinfo);
@@ -611,7 +615,6 @@ do_move(Gameinfo* gameinfo, char* command, int* passes, int force)
 
     if (opt_showboard) {
         twoplayer_showboard();
 
     if (opt_showboard) {
         twoplayer_showboard();
-        printf("GNU Go is thinking...\n");
     }
 
     if (force) {
     }
 
     if (force) {
@@ -622,7 +625,7 @@ do_move(Gameinfo* gameinfo, char* command, int* passes, int force)
     }
 
     gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
     }
 
     gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
-    return computer_move(gameinfo, passes);
+    return computer_move(gameinfo, passes, receive_fifo_fd);
 }
 
 /*
 }
 
 /*
@@ -630,8 +633,11 @@ do_move(Gameinfo* gameinfo, char* command, int* passes, int force)
  */
 
 static int
  */
 
 static int
-do_pass(Gameinfo* gameinfo, int* passes, int force)
+do_pass(Gameinfo* gameinfo, int* passes, int force,
+        int transmit_fifo_fd, int receive_fifo_fd)
 {
 {
+    twoplayer_send_move(NO_MOVE,transmit_fifo_fd);
+
     (*passes)++;
     init_sgf(gameinfo);
     gnugo_play_move(PASS_MOVE, gameinfo->to_move);
     (*passes)++;
     init_sgf(gameinfo);
     gnugo_play_move(PASS_MOVE, gameinfo->to_move);
@@ -646,7 +652,7 @@ do_pass(Gameinfo* gameinfo, int* passes, int force)
         return 0;
     }
 
         return 0;
     }
 
-    return computer_move(gameinfo, passes);
+    return computer_move(gameinfo, passes, receive_fifo_fd);
 }
 
 /*
 }
 
 /*
@@ -657,6 +663,27 @@ void play_twoplayer(SGFTree* tree, Gameinfo* gameinfo, char* filename, char* unt
 {
     int sz;
 
 {
     int sz;
 
+    int transmit_fifo_fd, receive_fifo_fd;
+    if (mknod(MASTER_FIFO_NAME, S_IFIFO | 0666, 0) == 0) {
+        gameinfo->computer_player = WHITE; // We are black, so our opponent is white.
+        printf("Waiting for other player to connect.\n");
+        transmit_fifo_fd = open(MASTER_FIFO_NAME, O_WRONLY);
+        receive_fifo_fd = open(SLAVE_FIFO_NAME, O_RDONLY);
+    } else {
+        gameinfo->computer_player = BLACK; // We are white, so our opponent is black.
+        if (mknod(SLAVE_FIFO_NAME, S_IFIFO | 0666, 0) == 0) {
+            receive_fifo_fd = open(MASTER_FIFO_NAME, O_RDONLY);
+            transmit_fifo_fd = open(SLAVE_FIFO_NAME, O_WRONLY);
+        } else {
+            printf("ERROR: Failed to create both master and slave FIFO.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+    // Allow both master and slave to attempt removal. Ignore error code since
+    // this is a best-effort situation for now.
+    unlink(MASTER_FIFO_NAME);
+    unlink(SLAVE_FIFO_NAME);
+
     setvbuf(stdout, (char*)NULL, _IONBF, 0); /* No buffering. */
 
     sgftree = *tree;
     setvbuf(stdout, (char*)NULL, _IONBF, 0); /* No buffering. */
 
     sgftree = *tree;
@@ -681,19 +708,23 @@ void play_twoplayer(SGFTree* tree, Gameinfo* gameinfo, char* filename, char* unt
         sgf_initialized = 0;
     }
 
         sgf_initialized = 0;
     }
 
-    do_play_twoplayer(gameinfo);
+    do_play_twoplayer(gameinfo, transmit_fifo_fd, receive_fifo_fd);
     printf("\nThanks! for playing GNU Go.\n\n");
 
     printf("\nThanks! for playing GNU Go.\n\n");
 
+    close(transmit_fifo_fd);
+    close(receive_fifo_fd);
+
     /* main() frees the tree and we might have changed it. */
     *tree = sgftree;
 }
 
     /* main() frees the tree and we might have changed it. */
     *tree = sgftree;
 }
 
-void do_play_twoplayer(Gameinfo* gameinfo)
+void do_play_twoplayer(Gameinfo* gameinfo, int transmit_fifo_fd, int receive_fifo_fd)
 {
 {
-    int m, num;
-    float fnum;
+    //int m;
+    int num;
+    //float fnum;
     int passes = 0; /* two passes and its over */
     int passes = 0; /* two passes and its over */
-    int tmp;
+    //int tmp;
     char line[80];
     char* line_ptr = line;
     char* command;
     char line[80];
     char* line_ptr = line;
     char* command;
@@ -710,8 +741,8 @@ void do_play_twoplayer(Gameinfo* gameinfo)
         current_score_estimate = NO_SCORE;
 
         /* Allow resignation at interface level (the engine may still be not
         current_score_estimate = NO_SCORE;
 
         /* Allow resignation at interface level (the engine may still be not
-     * allowed to resign.
-     */
+         * allowed to resign.
+         */
         resignation_allowed = 1;
 
         printf("\nBeginning two player game.\n\n");
         resignation_allowed = 1;
 
         printf("\nBeginning two player game.\n\n");
@@ -719,7 +750,7 @@ void do_play_twoplayer(Gameinfo* gameinfo)
 
         /* Does the computer play first?  If so, make a move. */
         if (gameinfo->computer_player == gameinfo->to_move)
 
         /* Does the computer play first?  If so, make a move. */
         if (gameinfo->computer_player == gameinfo->to_move)
-            state = computer_move(gameinfo, &passes);
+            state = computer_move(gameinfo, &passes, receive_fifo_fd);
 
         /* main ANSI Play loop */
         while (state == 0) {
 
         /* main ANSI Play loop */
         while (state == 0) {
@@ -749,7 +780,7 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                 /* Get the command or move. */
                 switch (get_command(command)) {
                 case RESIGN:
                 /* Get the command or move. */
                 switch (get_command(command)) {
                 case RESIGN:
-                    state = twoplayer_endgame(gameinfo, 1);
+                    //state = twoplayer_endgame(gameinfo, 1);
                     break;
 
                 case END:
                     break;
 
                 case END:
@@ -775,71 +806,75 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                     break;
 
                 case SETBOARDSIZE:
                     break;
 
                 case SETBOARDSIZE:
-                    if (sgf_initialized) {
-                        printf("Boardsize cannot be changed after record is started!\n");
-                        break;
-                    }
-                    command += 10;
-                    if (sscanf(command, "%d", &num) != 1) {
-                        printf("\nInvalid command syntax!\n");
-                        break;
-                    }
-                    if (!check_boardsize(num, stdout))
-                        break;
-                    /* Init board. */
-                    board_size = num;
-                    clear_board();
-                    /* In case max handicap changes on smaller board. */
-                    gameinfo->handicap = place_fixed_handicap(gameinfo->handicap);
-                    sgfOverwritePropertyInt(sgftree.root, "SZ", board_size);
-                    sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap);
+                    printf("Board size modification prohibited in two player mode.\n");
+                    //if (sgf_initialized) {
+                    //    printf("Boardsize cannot be changed after record is started!\n");
+                    //    break;
+                    //}
+                    //command += 10;
+                    //if (sscanf(command, "%d", &num) != 1) {
+                    //    printf("\nInvalid command syntax!\n");
+                    //    break;
+                    //}
+                    //if (!check_boardsize(num, stdout))
+                    //    break;
+                    ///* Init board. */
+                    //board_size = num;
+                    //clear_board();
+                    ///* In case max handicap changes on smaller board. */
+                    //gameinfo->handicap = place_fixed_handicap(gameinfo->handicap);
+                    //sgfOverwritePropertyInt(sgftree.root, "SZ", board_size);
+                    //sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap);
                     break;
 
                 case SETHANDICAP:
                     break;
 
                 case SETHANDICAP:
-                    if (sgf_initialized) {
-                        printf("Handicap cannot be changed after game is started!\n");
-                        break;
-                    }
-                    command += 9;
-                    if (sscanf(command, "%d", &num) != 1) {
-                        printf("\nInvalid command syntax!\n");
-                        break;
-                    }
-                    if (num < 0 || num > MAX_HANDICAP) {
-                        printf("\nInvalid handicap: %d\n", num);
-                        break;
-                    }
-                    /* Init board. */
-                    clear_board();
-                    /* Place stones on board but don't record sgf 
-          * in case we change more info. */
-                    gameinfo->handicap = place_fixed_handicap(num);
-                    printf("\nSet handicap to %d\n", gameinfo->handicap);
-                    gameinfo->to_move = (gameinfo->handicap ? WHITE : BLACK);
+                    printf("Handicap modification prohibited in two player mode.\n");
+                    //if (sgf_initialized) {
+                    //    printf("Handicap cannot be changed after game is started!\n");
+                    //    break;
+                    //}
+                    //command += 9;
+                    //if (sscanf(command, "%d", &num) != 1) {
+                    //    printf("\nInvalid command syntax!\n");
+                    //    break;
+                    //}
+                    //if (num < 0 || num > MAX_HANDICAP) {
+                    //    printf("\nInvalid handicap: %d\n", num);
+                    //    break;
+                    //}
+                    ///* Init board. */
+                    //clear_board();
+                    ///* Place stones on board but don't record sgf 
+                       // * in case we change more info. */
+                    //gameinfo->handicap = place_fixed_handicap(num);
+                    //printf("\nSet handicap to %d\n", gameinfo->handicap);
+                    //gameinfo->to_move = (gameinfo->handicap ? WHITE : BLACK);
                     break;
 
                 case FREEHANDICAP:
                     break;
 
                 case FREEHANDICAP:
-                    if (sgf_initialized) {
-                        printf("Handicap cannot be changed after game is started!\n");
-                        break;
-                    }
-                    while (*command && *command != ' ')
-                        command++;
-                    twoplayer_free_handicap(gameinfo, command);
+                    printf("Handicap modification prohibited in two player mode.\n");
+                    //if (sgf_initialized) {
+                    //    printf("Handicap cannot be changed after game is started!\n");
+                    //    break;
+                    //}
+                    //while (*command && *command != ' ')
+                    //    command++;
+                    //twoplayer_free_handicap(gameinfo, command);
                     break;
 
                 case SETKOMI:
                     break;
 
                 case SETKOMI:
-                    if (sgf_initialized) {
-                        printf("Komi cannot be modified after game record is started!\n");
-                        break;
-                    }
-                    command += 5;
-                    if (sscanf(command, "%f", &fnum) != 1) {
-                        printf("\nInvalid command syntax!\n");
-                        break;
-                    }
-                    komi = fnum;
-                    printf("\nSet Komi to %.1f\n", komi);
+                    printf("Komi modification prohibited in two player mode.\n");
+                    //if (sgf_initialized) {
+                    //    printf("Komi cannot be modified after game record is started!\n");
+                    //    break;
+                    //}
+                    //command += 5;
+                    //if (sscanf(command, "%f", &fnum) != 1) {
+                    //    printf("\nInvalid command syntax!\n");
+                    //    break;
+                    //}
+                    //komi = fnum;
+                    //printf("\nSet Komi to %.1f\n", komi);
                     break;
 
                 case SETDEPTH:
                     break;
 
                 case SETDEPTH:
@@ -868,92 +903,100 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                     break;
 
                 case FORCE:
                     break;
 
                 case FORCE:
-                    command += 6; /* skip the force part... */
-                    switch (get_command(command)) {
-                    case MOVE:
-                        state = do_move(gameinfo, command, &passes, 1);
-                        break;
-                    case PASS:
-                        state = do_pass(gameinfo, &passes, 1);
-                        break;
-                    default:
-                        printf("Illegal forced move: %s %d\n", command,
-                            get_command(command));
-                        break;
-                    }
+                    printf("No!\n");
+                    //command += 6; /* skip the force part... */
+                    //switch (get_command(command)) {
+                    //case MOVE:
+                    //    state = do_move(gameinfo, command, &passes, 1);
+                    //    break;
+                    //case PASS:
+                    //    state = do_pass(gameinfo, &passes, 1);
+                    //    break;
+                    //default:
+                    //    printf("Illegal forced move: %s %d\n", command,
+                    //        get_command(command));
+                    //    break;
+                    //}
                     break;
 
                 case MOVE:
                     break;
 
                 case MOVE:
-                    state = do_move(gameinfo, command, &passes, 0);
+                    state = do_move(gameinfo, command, &passes, 0, transmit_fifo_fd, receive_fifo_fd);
                     break;
 
                 case PASS:
                     break;
 
                 case PASS:
-                    state = do_pass(gameinfo, &passes, 0);
+                    state = do_pass(gameinfo, &passes, 0, transmit_fifo_fd, receive_fifo_fd);
                     break;
 
                 case PLAY:
                     break;
 
                 case PLAY:
-                    command += 5;
-                    if (sscanf(command, "%d", &num) != 1) {
-                        printf("\nInvalid command syntax!\n");
-                        break;
-                    }
-                    if (num >= 0)
-                        for (m = 0; m < num; m++) {
-                            gameinfo->computer_player
-                                = OTHER_COLOR(gameinfo->computer_player);
-                            state = computer_move(gameinfo, &passes);
-                            if (state)
-                                break;
-                            if (passes >= 2)
-                                break;
-                        }
-                    else {
-                        printf("\nInvalid number of moves specified: %d\n", num);
-                        break;
-                    }
+                    printf("Invalid command in two player mode.\n");
+                    //command += 5;
+                    //if (sscanf(command, "%d", &num) != 1) {
+                    //    printf("\nInvalid command syntax!\n");
+                    //    break;
+                    //}
+                    //if (num >= 0)
+                    //    for (m = 0; m < num; m++) {
+                    //        gameinfo->computer_player
+                    //            = OTHER_COLOR(gameinfo->computer_player);
+                    //        state = computer_move(gameinfo, &passes);
+                    //        if (state)
+                    //            break;
+                    //        if (passes >= 2)
+                    //            break;
+                    //    }
+                    //else {
+                    //    printf("\nInvalid number of moves specified: %d\n", num);
+                    //    break;
+                    //}
                     break;
 
                 case PLAYBLACK:
                     break;
 
                 case PLAYBLACK:
-                    if (gameinfo->computer_player == WHITE)
-                        gameinfo->computer_player = BLACK;
-                    if (gameinfo->computer_player == gameinfo->to_move)
-                        state = computer_move(gameinfo, &passes);
+                    printf("Invalid command in two player mode.\n");
+                    //if (gameinfo->computer_player == WHITE)
+                    //    gameinfo->computer_player = BLACK;
+                    //if (gameinfo->computer_player == gameinfo->to_move)
+                    //    state = computer_move(gameinfo, &passes);
                     break;
 
                 case PLAYWHITE:
                     break;
 
                 case PLAYWHITE:
-                    if (gameinfo->computer_player == BLACK)
-                        gameinfo->computer_player = WHITE;
-                    if (gameinfo->computer_player == gameinfo->to_move)
-                        state = computer_move(gameinfo, &passes);
+                    printf("Invalid command in two player mode.\n");
+                    //if (gameinfo->computer_player == BLACK)
+                    //    gameinfo->computer_player = WHITE;
+                    //if (gameinfo->computer_player == gameinfo->to_move)
+                    //    state = computer_move(gameinfo, &passes);
                     break;
 
                 case SWITCH:
                     break;
 
                 case SWITCH:
-                    gameinfo->computer_player = OTHER_COLOR(gameinfo->computer_player);
-                    state = computer_move(gameinfo, &passes);
+                    printf("Invalid command in two player mode.\n");
+                    //gameinfo->computer_player = OTHER_COLOR(gameinfo->computer_player);
+                    //state = computer_move(gameinfo, &passes);
                     break;
 
                 case UNDO:
                 case CMD_BACK:
                     break;
 
                 case UNDO:
                 case CMD_BACK:
-                    if (undo_move(1)) {
-                        sgftreeAddComment(&sgftree, "undone");
-                        sgftreeBack(&sgftree);
-                        gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
-                    } else
-                        printf("\nCan't undo.\n");
+                    printf("No undo in two player mode.\n");
+                    //if (undo_move(1)) {
+                    //    sgftreeAddComment(&sgftree, "undone");
+                    //    sgftreeBack(&sgftree);
+                    //    gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);
+                    //} else
+                    //    printf("\nCan't undo.\n");
                     break;
 
                 case CMD_FORWARD:
                     break;
 
                 case CMD_FORWARD:
-                    if (sgftreeForward(&sgftree))
-                        gameinfo->to_move = gnugo_play_sgfnode(sgftree.lastnode,
-                            gameinfo->to_move);
-                    else
-                        printf("\nEnd of game tree.\n");
+                    printf("Invalid command in two player mode.\n");
+                    //if (sgftreeForward(&sgftree))
+                    //    gameinfo->to_move = gnugo_play_sgfnode(sgftree.lastnode,
+                    //        gameinfo->to_move);
+                    //else
+                    //    printf("\nEnd of game tree.\n");
                     break;
 
                 case CMD_LAST:
                     break;
 
                 case CMD_LAST:
-                    while (sgftreeForward(&sgftree))
-                        gameinfo->to_move = gnugo_play_sgfnode(sgftree.lastnode,
-                            gameinfo->to_move);
+                    printf("Invalid command in two player mode.\n");
+                    //while (sgftreeForward(&sgftree))
+                    //    gameinfo->to_move = gnugo_play_sgfnode(sgftree.lastnode,
+                    //        gameinfo->to_move);
                     break;
 
                 case COMMENT:
                     break;
 
                 case COMMENT:
@@ -969,49 +1012,57 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                     break;
 
                 case CMD_DEAD:
                     break;
 
                 case CMD_DEAD:
-                    silent_examine_position(FULL_EXAMINE_DRAGONS);
-                    showdead = !showdead;
+                    printf("Invalid command in two player mode.\n");
+                    //silent_examine_position(FULL_EXAMINE_DRAGONS);
+                    //showdead = !showdead;
                     break;
 
                 case CMD_CAPTURE:
                     break;
 
                 case CMD_CAPTURE:
-                    strtok(command, " ");
-                    showcapture(strtok(NULL, " "));
+                    printf("Invalid command in two player mode.\n");
+                    //strtok(command, " ");
+                    //showcapture(strtok(NULL, " "));
                     break;
 
                 case CMD_DEFEND:
                     break;
 
                 case CMD_DEFEND:
-                    strtok(command, " ");
-                    showdefense(strtok(NULL, " "));
+                    printf("Invalid command in two player mode.\n");
+                    //strtok(command, " ");
+                    //showdefense(strtok(NULL, " "));
                     break;
 
                 case CMD_SHOWMOYO:
                     break;
 
                 case CMD_SHOWMOYO:
-                    tmp = printmoyo;
-                    printmoyo = PRINTMOYO_MOYO;
-                    silent_examine_position(EXAMINE_DRAGONS);
-                    printmoyo = tmp;
+                    printf("Invalid command in two player mode.\n");
+                    //tmp = printmoyo;
+                    //printmoyo = PRINTMOYO_MOYO;
+                    //silent_examine_position(EXAMINE_DRAGONS);
+                    //printmoyo = tmp;
                     break;
 
                 case CMD_SHOWTERRI:
                     break;
 
                 case CMD_SHOWTERRI:
-                    tmp = printmoyo;
-                    printmoyo = PRINTMOYO_TERRITORY;
-                    silent_examine_position(EXAMINE_DRAGONS);
-                    printmoyo = tmp;
+                    printf("Invalid command in two player mode.\n");
+                    //tmp = printmoyo;
+                    //printmoyo = PRINTMOYO_TERRITORY;
+                    //silent_examine_position(EXAMINE_DRAGONS);
+                    //printmoyo = tmp;
                     break;
 
                 case CMD_SHOWAREA:
                     break;
 
                 case CMD_SHOWAREA:
-                    tmp = printmoyo;
-                    printmoyo = PRINTMOYO_AREA;
-                    silent_examine_position(EXAMINE_DRAGONS);
-                    printmoyo = tmp;
+                    printf("Invalid command in two player mode.\n");
+                    //tmp = printmoyo;
+                    //printmoyo = PRINTMOYO_AREA;
+                    //silent_examine_position(EXAMINE_DRAGONS);
+                    //printmoyo = tmp;
                     break;
 
                 case CMD_SHOWDRAGONS:
                     break;
 
                 case CMD_SHOWDRAGONS:
-                    silent_examine_position(EXAMINE_DRAGONS);
-                    showboard(1);
+                    printf("Invalid command in two player mode.\n");
+                    //silent_examine_position(EXAMINE_DRAGONS);
+                    //showboard(1);
                     break;
 
                 case CMD_GOTO:
                     break;
 
                 case CMD_GOTO:
-                    strtok(command, " ");
-                    twoplayer_goto(gameinfo, strtok(NULL, " "));
+                    printf("Invalid command in two player mode.\n");
+                    //strtok(command, " ");
+                    //twoplayer_goto(gameinfo, strtok(NULL, " "));
                     break;
 
                 case CMD_SAVE:
                     break;
 
                 case CMD_SAVE:
@@ -1023,37 +1074,40 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                         /* make sure we are saving proper handicap */
                         init_sgf(gameinfo);
                         writesgf(sgftree.root, tmpstring);
                         /* make sure we are saving proper handicap */
                         init_sgf(gameinfo);
                         writesgf(sgftree.root, tmpstring);
-                        printf("You may resume the game");
-                        printf(" with -l %s --mode twoplayer\n", tmpstring);
-                        printf("or load %s\n", tmpstring);
+                        printf("Game saved at %s for offline use.\n", tmpstring);
+                        //printf("You may resume the game");
+                        //printf(" with -l %s --mode twoplayer\n", tmpstring);
+                        //printf("or load %s\n", tmpstring);
                     } else
                         printf("Please specify filename\n");
                     break;
 
                 case CMD_LOAD:
                     } else
                         printf("Please specify filename\n");
                     break;
 
                 case CMD_LOAD:
-                    strtok(command, " ");
-                    tmpstring = strtok(NULL, " ");
-                    if (tmpstring) {
-                        /* discard newline */
-                        tmpstring[strlen(tmpstring) - 1] = 0;
-                        if (!sgftree_readfile(&sgftree, tmpstring)) {
-                            fprintf(stderr, "Cannot open or parse '%s'\n", tmpstring);
-                            break;
-                        }
-                        /* to avoid changing handicap etc. */
-                        if (gameinfo_play_sgftree(gameinfo, &sgftree, NULL) == EMPTY)
-                            fprintf(stderr, "Cannot load '%s'\n", tmpstring);
-                        else {
-                            sgf_initialized = 1;
-                            sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap);
-                        }
-                    } else
-                        printf("Please specify a filename\n");
+                    printf("Invalid command in two player mode.\n");
+                    //strtok(command, " ");
+                    //tmpstring = strtok(NULL, " ");
+                    //if (tmpstring) {
+                    //    /* discard newline */
+                    //    tmpstring[strlen(tmpstring) - 1] = 0;
+                    //    if (!sgftree_readfile(&sgftree, tmpstring)) {
+                    //        fprintf(stderr, "Cannot open or parse '%s'\n", tmpstring);
+                    //        break;
+                    //    }
+                    //    /* to avoid changing handicap etc. */
+                    //    if (gameinfo_play_sgftree(gameinfo, &sgftree, NULL) == EMPTY)
+                    //        fprintf(stderr, "Cannot load '%s'\n", tmpstring);
+                    //    else {
+                    //        sgf_initialized = 1;
+                    //        sgfOverwritePropertyInt(sgftree.root, "HA", gameinfo->handicap);
+                    //    }
+                    //} else
+                    //    printf("Please specify a filename\n");
                     break;
 
                 case CMD_LISTDRAGONS:
                     break;
 
                 case CMD_LISTDRAGONS:
-                    silent_examine_position(EXAMINE_DRAGONS);
-                    show_dragons();
+                    printf("Invalid command in two player mode.\n");
+                    //silent_examine_position(EXAMINE_DRAGONS);
+                    //show_dragons();
                     break;
 
                 default:
                     break;
 
                 default:
@@ -1061,8 +1115,10 @@ void do_play_twoplayer(Gameinfo* gameinfo)
                     break;
                 }
 
                     break;
                 }
 
-                if (passes >= 2)
+                if (passes >= 2) {
+                    twoplayer_send_move(NO_MOVE,transmit_fifo_fd);
                     state = twoplayer_endgame(gameinfo, 0);
                     state = twoplayer_endgame(gameinfo, 0);
+                }
             }
 #if READLINE
             free(line_ptr);
             }
 #if READLINE
             free(line_ptr);
@@ -1227,133 +1283,133 @@ twoplayer_count(Gameinfo* gameinfo)
     who_wins(gameinfo->computer_player, stdout);
 }
 
     who_wins(gameinfo->computer_player, stdout);
 }
 
-static void
-showcapture(char* line)
-{
-    int str;
-    int move;
-
-    gg_assert(line);
-    str = string_to_location(board_size, line);
-    if (str == NO_MOVE || board[str] == EMPTY) {
-        printf("\ninvalid point!\n");
-        return;
-    }
-
-    if (attack(str, &move))
-        mprintf("\nSuccessful attack of %1m at %1m\n", str, move);
-    else
-        mprintf("\n%1m cannot be attacked\n", str);
-}
-
-static void
-showdefense(char* line)
-{
-    int str;
-    int move;
-
-    gg_assert(line);
-    str = string_to_location(board_size, line);
-    if (str == NO_MOVE || board[str] == EMPTY) {
-        printf("\ninvalid point!\n");
-        return;
-    }
-
-    if (attack(str, NULL)) {
-        if (find_defense(str, &move))
-            mprintf("\nSuccessful defense of %1m at %1m\n", str, move);
-        else
-            mprintf("\n%1m cannot be defended\n", str);
-    } else
-        mprintf("\nThere is no need to defend %1m\n", str);
-}
-
-static void
-twoplayer_goto(Gameinfo* gameinfo, char* line)
-{
-    const char* movenumber = line;
-
-    if (!line)
-        return;
-
-    if (!strncmp(line, "last", 4))
-        movenumber = "9999";
-    else if (!strncmp(line, "first", 4))
-        movenumber = "1";
-
-    printf("goto %s\n", movenumber);
-    gameinfo_play_sgftree(gameinfo, &sgftree, movenumber);
-}
-
-static void
-twoplayer_free_handicap(Gameinfo* gameinfo, char* handicap_string)
-{
-    int handi;
-    int i;
-    char line[80];
-    int stones[MAX_BOARD * MAX_BOARD];
-
-    if (sscanf(handicap_string, "%d", &handi) == 1) {
-        /* GNU Go is to place handicap */
-        if (handi < 0 || handi == 1) {
-            printf("\nInvalid command syntax!\n");
-            return;
-        }
-
-        clear_board();
-        handi = place_free_handicap(handi);
-        printf("\nPlaced %d stones of free handicap.\n", handi);
-    } else { /* User is to place handicap */
-        clear_board();
-        handi = 0;
-
-        while (1) {
-            twoplayer_showboard();
-            printf("\nType in coordinates of next handicap stone, or one of the following commands:\n");
-            printf("  undo        take back the last stone placed\n");
-            printf("  clear       remove all the stones placed so far\n");
-            printf("  done        finish placing handicap\n\n");
-            printf("You have placed %d handicap stone(s) so far.\n\n", handi);
-
-            if (!fgets(line, 80, stdin))
-                return; /* EOF or some error */
-            for (i = 0; i < 80; i++)
-                line[i] = tolower((int)line[i]);
-
-            if (!strncmp(line, "undo", 4)) {
-                if (!handi)
-                    printf("\nNothing to undo.\n");
-                else {
-                    remove_stone(stones[--handi]);
-                    gprintf("\nRemoved the stone at %m.\n", I(stones[handi]),
-                        J(stones[handi]));
-                }
-            } else if (!strncmp(line, "clear", 5)) {
-                clear_board();
-                handi = 0;
-            } else if (!strncmp(line, "done", 4)) {
-                if (handi == 1) /* Don't bother with checks later */
-                    printf("\nHandicap cannot be one stone. Either add "
-                           "some more, or delete the only stone.\n");
-                else
-                    break;
-            } else {
-                int pos = string_to_location(board_size, line);
-                if (pos != NO_MOVE) {
-                    if (board[pos] != EMPTY)
-                        printf("\nThere's already a stone there.\n");
-                    else {
-                        add_stone(pos, BLACK);
-                        stones[handi++] = pos;
-                    }
-                } else
-                    printf("\nInvalid command: %s", line);
-            }
-        }
-    }
-    gameinfo->handicap = handi;
-    gameinfo->to_move = (handi ? WHITE : BLACK);
-}
+//static void
+//showcapture(char* line)
+//{
+//    int str;
+//    int move;
+//
+//    gg_assert(line);
+//    str = string_to_location(board_size, line);
+//    if (str == NO_MOVE || board[str] == EMPTY) {
+//        printf("\ninvalid point!\n");
+//        return;
+//    }
+//
+//    if (attack(str, &move))
+//        mprintf("\nSuccessful attack of %1m at %1m\n", str, move);
+//    else
+//        mprintf("\n%1m cannot be attacked\n", str);
+//}
+
+//static void
+//showdefense(char* line)
+//{
+//    int str;
+//    int move;
+//
+//    gg_assert(line);
+//    str = string_to_location(board_size, line);
+//    if (str == NO_MOVE || board[str] == EMPTY) {
+//        printf("\ninvalid point!\n");
+//        return;
+//    }
+//
+//    if (attack(str, NULL)) {
+//        if (find_defense(str, &move))
+//            mprintf("\nSuccessful defense of %1m at %1m\n", str, move);
+//        else
+//            mprintf("\n%1m cannot be defended\n", str);
+//    } else
+//        mprintf("\nThere is no need to defend %1m\n", str);
+//}
+
+//static void
+//twoplayer_goto(Gameinfo* gameinfo, char* line)
+//{
+//    const char* movenumber = line;
+//
+//    if (!line)
+//        return;
+//
+//    if (!strncmp(line, "last", 4))
+//        movenumber = "9999";
+//    else if (!strncmp(line, "first", 4))
+//        movenumber = "1";
+//
+//    printf("goto %s\n", movenumber);
+//    gameinfo_play_sgftree(gameinfo, &sgftree, movenumber);
+//}
+
+//static void
+//twoplayer_free_handicap(Gameinfo* gameinfo, char* handicap_string)
+//{
+//    int handi;
+//    int i;
+//    char line[80];
+//    int stones[MAX_BOARD * MAX_BOARD];
+//
+//    if (sscanf(handicap_string, "%d", &handi) == 1) {
+//        /* GNU Go is to place handicap */
+//        if (handi < 0 || handi == 1) {
+//            printf("\nInvalid command syntax!\n");
+//            return;
+//        }
+//
+//        clear_board();
+//        handi = place_free_handicap(handi);
+//        printf("\nPlaced %d stones of free handicap.\n", handi);
+//    } else { /* User is to place handicap */
+//        clear_board();
+//        handi = 0;
+//
+//        while (1) {
+//            twoplayer_showboard();
+//            printf("\nType in coordinates of next handicap stone, or one of the following commands:\n");
+//            printf("  undo        take back the last stone placed\n");
+//            printf("  clear       remove all the stones placed so far\n");
+//            printf("  done        finish placing handicap\n\n");
+//            printf("You have placed %d handicap stone(s) so far.\n\n", handi);
+//
+//            if (!fgets(line, 80, stdin))
+//                return; /* EOF or some error */
+//            for (i = 0; i < 80; i++)
+//                line[i] = tolower((int)line[i]);
+//
+//            if (!strncmp(line, "undo", 4)) {
+//                if (!handi)
+//                    printf("\nNothing to undo.\n");
+//                else {
+//                    remove_stone(stones[--handi]);
+//                    gprintf("\nRemoved the stone at %m.\n", I(stones[handi]),
+//                        J(stones[handi]));
+//                }
+//            } else if (!strncmp(line, "clear", 5)) {
+//                clear_board();
+//                handi = 0;
+//            } else if (!strncmp(line, "done", 4)) {
+//                if (handi == 1) /* Don't bother with checks later */
+//                    printf("\nHandicap cannot be one stone. Either add "
+//                           "some more, or delete the only stone.\n");
+//                else
+//                    break;
+//            } else {
+//                int pos = string_to_location(board_size, line);
+//                if (pos != NO_MOVE) {
+//                    if (board[pos] != EMPTY)
+//                        printf("\nThere's already a stone there.\n");
+//                    else {
+//                        add_stone(pos, BLACK);
+//                        stones[handi++] = pos;
+//                    }
+//                } else
+//                    printf("\nInvalid command: %s", line);
+//            }
+//        }
+//    }
+//    gameinfo->handicap = handi;
+//    gameinfo->to_move = (handi ? WHITE : BLACK);
+//}
 
 /*
  * Local Variables:
 
 /*
  * Local Variables: