Subversion Repositories Games.Chess Giants

Rev

Rev 150 | Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 150 Rev 153
Line 13... Line 13...
13
 
13
 
14
// prototypes of local functions
14
// prototypes of local functions
15
static void PlayerEngine_Recv (player_t *player);
15
static void PlayerEngine_Recv (player_t *player);
16
static void PlayerEngine_Send (player_t *player);
16
static void PlayerEngine_Send (player_t *player);
17
static wchar_t *Move_BuildString (boardmove_t *move);
17
static wchar_t *Move_BuildString (boardmove_t *move);
-
 
18
static bool SendEngineHistoryToAuthor (void);
18
 
19
 
19
 
20
 
20
bool PlayerEngine_Init (player_t *player)
21
bool PlayerEngine_Init (player_t *player)
21
{
22
{
22
   // this function starts a chess engine as a child process. This process's stdin and
23
   // this function starts a chess engine as a child process. This process's stdin and
Line 79... Line 80...
79
      return (false);
80
      return (false);
80
   }
81
   }
81
 
82
 
82
   // optionally initialize the debug log file
83
   // optionally initialize the debug log file
83
   Debug_Init (L"Chess engine output.txt");
84
   Debug_Init (L"Chess engine output.txt");
-
 
85
   Debug_Log (L"===Using engine: %s [%s]===\n", program->friendly_name, chessengine_shellcommand);
84
 
86
 
85
   // build the init file full qualified path name and try to open it
87
   // build the init file full qualified path name and try to open it
86
   swprintf_s (chessengineinitfile_pathname, WCHAR_SIZEOF (chessengineinitfile_pathname), L"%s/engines/%s/init.txt", app_path, program->folder);
88
   swprintf_s (chessengineinitfile_pathname, WCHAR_SIZEOF (chessengineinitfile_pathname), L"%s/engines/%s/init.txt", app_path, program->folder);
87
   _wfopen_s (&fp, chessengineinitfile_pathname, L"r");
89
   _wfopen_s (&fp, chessengineinitfile_pathname, L"r");
88
 
90
 
89
   // could the init file be opened ?
91
   // could the init file be opened ?
90
   if (fp != NULL)
92
   if (fp != NULL)
91
   {
93
   {
92
      Debug_Log (L"===Found initialization file, parsing...===\n");
94
      Debug_Log (L"===Found initialization file, parsing...===\n", chessengineinitfile_pathname);
93
 
95
 
94
      // SMP HACK -- assume our engine is CECP compatible and set the max CPUs to use to core max - 1
96
      // SMP HACK -- assume our engine is CECP compatible and set the max CPUs to use to core max - 1
95
      // (the computer will look like hung if all CPU is taken)
97
      // (the computer will look like hung if all CPU is taken)
96
      GetSystemInfo (&sysinfo); // get the number of cores and build the corresponding engine initialization order
98
      GetSystemInfo (&sysinfo); // get the number of cores and build the corresponding engine initialization order
97
      Player_SendBuffer_Add (player, 1000, L"mt %d\n", max (1, sysinfo.dwNumberOfProcessors - 1));
99
      Player_SendBuffer_Add (player, 1000, L"mt %d\n", max (1, sysinfo.dwNumberOfProcessors - 1));
Line 166... Line 168...
166
   do_update = false;
168
   do_update = false;
167
 
169
 
168
   // get current and opposite players
170
   // get current and opposite players
169
   current_player = Player_GetCurrent ();
171
   current_player = Player_GetCurrent ();
170
   opposite_player = Player_GetOpposite ();
172
   opposite_player = Player_GetOpposite ();
-
 
173
 
-
 
174
   // is the game still alive AND has the engine just died ?
-
 
175
   if ((the_board.game_state == STATE_PLAYING) && !pipe_isalive (fpipe))
-
 
176
   {
-
 
177
      Debug_Log (L"===Unrecoverable engine error: opponent wins!===\n");
-
 
178
 
-
 
179
      // if opponent player is human, play the victory sound, else, play defeat sound at the center of the board
-
 
180
      Audio_PlaySound (opposite_player->type == PLAYER_HUMAN ? SOUNDTYPE_VICTORY : SOUNDTYPE_DEFEAT, 0.0f, 0.0f, 0.04f);
-
 
181
 
-
 
182
      // display a crash notification dialog box
-
 
183
      if (MessageBox (hMainWnd, LOCALIZE (L"Error_EngineCrashed"), LOCALIZE (L"ImportantMessage"), MB_ICONWARNING | MB_YESNO) == IDYES)
-
 
184
         if (!SendEngineHistoryToAuthor ())
-
 
185
            MessageBox (hMainWnd, LOCALIZE (L"NoInternetConnection"), LOCALIZE (L"FatalError"), MB_ICONWARNING | MB_OK); // send the game engine history to the author and display an error message if failed
-
 
186
 
-
 
187
      // and display the game over dialog box
-
 
188
      the_board.game_state = (opposite_player->color == COLOR_BLACK ? STATE_WHITEWIN_RESIGNORFORFEIT : STATE_BLACKWIN_RESIGNORFORFEIT);
-
 
189
      DialogBox_EndGame ();
-
 
190
 
-
 
191
      do_update = true; // remember to update the 3D scene
-
 
192
   }
171
 
193
 
172
   // read from pipe (non-blocking)
194
   // read from pipe (non-blocking)
173
   PlayerEngine_Recv (player);
195
   PlayerEngine_Recv (player);
174
 
196
 
175
   ////////////////
197
   ////////////////
Line 269... Line 291...
269
 
291
 
270
      // has the game ended already ?
292
      // has the game ended already ?
271
      if (the_board.game_state > STATE_PLAYING)
293
      if (the_board.game_state > STATE_PLAYING)
272
         continue; // ignore all that the engine tells us. Game is over already.
294
         continue; // ignore all that the engine tells us. Game is over already.
273
 
295
 
274
      // else is it a normal move ?
296
      // else is it a normal move AND not a polyglot error ?
275
      else if ((move_string = wcsstr (line_buffer, program->replystring_move)) != NULL)
297
      else if (((move_string = wcsstr (line_buffer, program->replystring_move)) != NULL) && (wcsstr (line_buffer, L"illegal") == NULL))
276
         move_string += wcslen (program->replystring_move); // go to the parsable data
298
         move_string += wcslen (program->replystring_move); // go to the parsable data
-
 
299
 
-
 
300
      // else is it an unrecoverable engine error ?
-
 
301
      else if (wcsstr (line_buffer, L"illegal") != NULL)
-
 
302
      {
-
 
303
         Debug_Log (L"===Unrecoverable engine error: opponent wins!===\n");
-
 
304
 
-
 
305
         // if opponent player is human, play the victory sound, else, play defeat sound at the center of the board
-
 
306
         Audio_PlaySound (opposite_player->type == PLAYER_HUMAN ? SOUNDTYPE_VICTORY : SOUNDTYPE_DEFEAT, 0.0f, 0.0f, 0.04f);
-
 
307
 
-
 
308
         // display a crash notification dialog box
-
 
309
         if (MessageBox (hMainWnd, LOCALIZE (L"Error_EngineCrashed"), LOCALIZE (L"ImportantMessage"), MB_ICONWARNING | MB_YESNO) == IDYES)
-
 
310
            if (!SendEngineHistoryToAuthor ())
-
 
311
               MessageBox (hMainWnd, LOCALIZE (L"NoInternetConnection"), LOCALIZE (L"FatalError"), MB_ICONWARNING | MB_OK); // send the game engine history to the author and display an error message if failed
-
 
312
 
-
 
313
         // and display the game over dialog box
-
 
314
         the_board.game_state = (opposite_player->color == COLOR_BLACK ? STATE_WHITEWIN_RESIGNORFORFEIT : STATE_BLACKWIN_RESIGNORFORFEIT);
-
 
315
         DialogBox_EndGame ();
-
 
316
 
-
 
317
         do_update = true; // remember to update the 3D scene
-
 
318
      }
277
 
319
 
278
      // else it's any other sort of line
320
      // else it's any other sort of line
279
      else
321
      else
280
         continue; // skip lines that don't contain any valid move data
322
         continue; // skip lines that don't contain any valid move data
281
 
323
 
Line 579... Line 621...
579
      wcscat_s  (output_string, WCHAR_SIZEOF (output_string), L"b");
621
      wcscat_s  (output_string, WCHAR_SIZEOF (output_string), L"b");
580
   else if (move->promotion_type == PART_QUEEN)
622
   else if (move->promotion_type == PART_QUEEN)
581
      wcscat_s  (output_string, WCHAR_SIZEOF (output_string), L"q");
623
      wcscat_s  (output_string, WCHAR_SIZEOF (output_string), L"q");
582
 
624
 
583
   return (output_string); // finished, return the move string
625
   return (output_string); // finished, return the move string
-
 
626
}
-
 
627
 
-
 
628
 
-
 
629
static bool SendEngineHistoryToAuthor (void)
-
 
630
{
-
 
631
   // this function upload the engine history to the remote server for debug purposes.
-
 
632
 
-
 
633
   static char history_buffer[512 * 1024];
-
 
634
   static char base64_buffer[1024 * 1024];
-
 
635
   static char http_buffer[1024 * 1024]; // used both for request and reply
-
 
636
 
-
 
637
   struct sockaddr_in service;
-
 
638
   struct hostent *hostinfo;
-
 
639
   int write_index;
-
 
640
   int read_index;
-
 
641
   int length;
-
 
642
   SOCKET s;
-
 
643
   FILE *fp;
-
 
644
 
-
 
645
   // get a hand on the log file and read its contents
-
 
646
   _wfopen_s (&fp, logfile_pathname, L"rb");
-
 
647
   if (fp == NULL)
-
 
648
      return (false); // couldn't open game history log file, return an error condition
-
 
649
   fseek (fp, 0, SEEK_END);
-
 
650
   length = ftell (fp); // get file size
-
 
651
   fseek (fp, 0, SEEK_SET);
-
 
652
   if (length > sizeof (base64_buffer) - 1)
-
 
653
      return (false); // history file too big, return an error condition
-
 
654
   fread (base64_buffer, 1, length, fp);
-
 
655
   base64_buffer[length] = 0; // terminate buffer ourselves
-
 
656
   fclose (fp);
-
 
657
   ConvertTo7BitASCII (history_buffer, sizeof (history_buffer), (wchar_t *) base64_buffer);
-
 
658
 
-
 
659
   // initialize the network subsystem if required
-
 
660
   if (!Network_Init ())
-
 
661
      return (false); // couldn't initialize WinSock, return an error condition
-
 
662
 
-
 
663
   // get our distribution server's IP address from the host name
-
 
664
   hostinfo = gethostbyname ("pmbaty.com");
-
 
665
   if (hostinfo == NULL)
-
 
666
      return (false); // couldn't resolve hostname, return an error condition
-
 
667
 
-
 
668
   // fill in the sockaddr server structure with the server hostinfo data
-
 
669
   service.sin_family = AF_INET;
-
 
670
   service.sin_addr.s_addr = inet_addr (inet_ntoa (*(struct in_addr *) hostinfo->h_addr_list[0]));
-
 
671
   service.sin_port = htons (80); // connect to webserver there (port 80)
-
 
672
 
-
 
673
   // create our socket
-
 
674
   if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
-
 
675
      return (false); // couldn't resolve hostname, return an error condition
-
 
676
 
-
 
677
   // connect to the distributor's webserver using that socket
-
 
678
   if (connect (s, (struct sockaddr *) &service, sizeof (service)) == -1)
-
 
679
   {
-
 
680
      closesocket (s); // finished communicating, close TCP socket
-
 
681
      return (false); // couldn't resolve hostname, return an error condition
-
 
682
   }
-
 
683
 
-
 
684
   // build the HTTP POST query and send it
-
 
685
   length = strlen ("data=") + base64_encode (base64_buffer, history_buffer, strlen (history_buffer));
-
 
686
   sprintf_s (http_buffer, sizeof (http_buffer),
-
 
687
      "POST /chess/sendcrash.php HTTP/1.1\r\n"
-
 
688
      "Host: pmbaty.com\r\n"
-
 
689
      "Content-Type: application/x-www-form-urlencoded\r\n"
-
 
690
      "Content-Length: %d\r\n"
-
 
691
      "Connection: close\r\n"
-
 
692
      "\r\n"
-
 
693
      "data=", length);
-
 
694
   strcat_s (http_buffer, sizeof (http_buffer), base64_buffer);
-
 
695
   length = strlen (http_buffer);
-
 
696
   write_index = send (s, http_buffer, length, 0); // send the HTTP query
-
 
697
   if (write_index != length)
-
 
698
   {
-
 
699
      closesocket (s); // finished communicating, close TCP socket
-
 
700
      return (false); // couldn't resolve hostname, return an error condition
-
 
701
   }
-
 
702
 
-
 
703
   // read the reply (10 seconds timeout)
-
 
704
   http_buffer[0] = 0;
-
 
705
   read_index = RecvWithTimeout (s, 10.0f, http_buffer, sizeof (http_buffer), 0);
-
 
706
   if (read_index < 1)
-
 
707
   {
-
 
708
      closesocket (s); // finished communicating, close TCP socket
-
 
709
      return (false); // couldn't resolve hostname, return an error condition
-
 
710
   }
-
 
711
 
-
 
712
   closesocket (s); // finished communicating, close TCP socket
-
 
713
 
-
 
714
   // terminate recv buffer ourselves
-
 
715
   http_buffer[read_index] = 0;
-
 
716
 
-
 
717
   //MessageBoxA (NULL, http_buffer, "HTTP response", MB_OK);
-
 
718
   return (strstr (http_buffer, "Success") != NULL); // and return whether the server accepted our post
584
}
719
}