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 | } |