Rev 39 | Rev 44 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 39 | Rev 40 | ||
---|---|---|---|
Line 35... | Line 35... | ||
35 | hChessEngineStdinRd = NULL; |
35 | hChessEngineStdinRd = NULL; |
36 | hChessEngineStdinWr = NULL; |
36 | hChessEngineStdinWr = NULL; |
37 | hChessEngineStdoutRd = NULL; |
37 | hChessEngineStdoutRd = NULL; |
38 | hChessEngineStdoutWr = NULL; |
38 | hChessEngineStdoutWr = NULL; |
39 | player->wants_hint = false; |
39 | player->wants_hint = false; |
- | 40 | ||
- | 41 | // load the selected engine parameters |
|
- | 42 | Config_LoadEngine (options.engine.program); |
|
40 | 43 | ||
41 | // build the chess engine module path and pathname |
44 | // build the chess engine module path and pathname |
42 | swprintf_s (chessenginemodule_path, WCHAR_SIZEOF (chessenginemodule_path), L"%s/engines/%s", app_path, options.engine.program); |
45 | swprintf_s (chessenginemodule_path, WCHAR_SIZEOF (chessenginemodule_path), L"%s/engines/%s", app_path, options.engine.program); |
43 | swprintf_s (chessenginemodule_pathname, WCHAR_SIZEOF (chessenginemodule_pathname), L"%s/engines/%s/%s", app_path, options.engine.program, options.engine.cmdline); |
46 | swprintf_s (chessenginemodule_pathname, WCHAR_SIZEOF (chessenginemodule_pathname), L"%s/engines/%s/%s", app_path, options.engine.program, options.engine.program_options.cmdline); |
44 | 47 | ||
45 | // prepare the pipes' security attributes |
48 | // prepare the pipes' security attributes |
46 | saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); |
49 | saAttr.nLength = sizeof (SECURITY_ATTRIBUTES); |
47 | saAttr.bInheritHandle = true; // set the bInheritHandle flag so pipe handles are inherited |
50 | saAttr.bInheritHandle = true; // set the bInheritHandle flag so pipe handles are inherited |
48 | saAttr.lpSecurityDescriptor = NULL; |
51 | saAttr.lpSecurityDescriptor = NULL; |
Line 61... | Line 64... | ||
61 | si.dwFlags = STARTF_USESTDHANDLES; |
64 | si.dwFlags = STARTF_USESTDHANDLES; |
62 | si.hStdInput = hChessEngineStdinRd; |
65 | si.hStdInput = hChessEngineStdinRd; |
63 | si.hStdOutput = hChessEngineStdoutWr; |
66 | si.hStdOutput = hChessEngineStdoutWr; |
64 | si.hStdError = hChessEngineStdoutWr; |
67 | si.hStdError = hChessEngineStdoutWr; |
65 | if (!CreateProcess (chessenginemodule_pathname, // module pathname |
68 | if (!CreateProcess (chessenginemodule_pathname, // module pathname |
66 | options.engine.cmdline, // command line |
69 | options.engine.program_options.cmdline, // command line |
67 | NULL, NULL, |
70 | NULL, NULL, |
68 | true, // handles are inherited |
71 | true, // handles are inherited |
69 | CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, |
72 | CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, |
70 | NULL, |
73 | NULL, |
71 | chessenginemodule_path, // process path |
74 | chessenginemodule_path, // process path |
Line 94... | Line 97... | ||
94 | { |
97 | { |
95 | Debug_Log (L"===Found initialization file, parsing...===\n"); |
98 | Debug_Log (L"===Found initialization file, parsing...===\n"); |
96 | 99 | ||
97 | // SMP HACK -- is our engine Crafty or GNU Chess ? if so, set the max CPUs to use to core max - 1 |
100 | // SMP HACK -- is our engine Crafty or GNU Chess ? if so, set the max CPUs to use to core max - 1 |
98 | // (the computer will look like hung if all CPU is taken) |
101 | // (the computer will look like hung if all CPU is taken) |
99 | if ((wcsistr (options.engine.name, L"Crafty" |
102 | if ((wcsistr (options.engine.program_options.name, L"Crafty") != NULL) || (wcsistr (options.engine.program_options.name, L"GNU Chess") != NULL)) |
100 | { |
103 | { |
101 | GetSystemInfo (&sysinfo); // get the number of cores and build the corresponding engine initialization order |
104 | GetSystemInfo (&sysinfo); // get the number of cores and build the corresponding engine initialization order |
102 | Player_SendBuffer_Add (player, 1000, L"mt %d\n", max (1, sysinfo.dwNumberOfProcessors - 1)); |
105 | Player_SendBuffer_Add (player, 1000, L"mt %d\n", max (1, sysinfo.dwNumberOfProcessors - 1)); |
103 | } |
106 | } |
104 | 107 | ||
Line 114... | Line 117... | ||
114 | 117 | ||
115 | fclose (fp); // finished, close the file |
118 | fclose (fp); // finished, close the file |
116 | } |
119 | } |
117 | 120 | ||
118 | // everything's okay, set engine name as the player's name |
121 | // everything's okay, set engine name as the player's name |
119 | wcscpy_s (player->name, WCHAR_SIZEOF (player->name), options.engine.name); |
122 | wcscpy_s (player->name, WCHAR_SIZEOF (player->name), options.engine.program_options.name); |
120 | 123 | ||
121 | return (true); // finished |
124 | return (true); // finished |
122 | } |
125 | } |
123 | 126 | ||
124 | 127 | ||
Line 129... | Line 132... | ||
129 | unsigned long exit_code; |
132 | unsigned long exit_code; |
130 | unsigned long handle_flags; |
133 | unsigned long handle_flags; |
131 | int attempt_index; |
134 | int attempt_index; |
132 | 135 | ||
133 | // send the engine a quit command |
136 | // send the engine a quit command |
134 | Player_SendBuffer_Add (player, 1000, options.engine.command_quit); |
137 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_quit); |
135 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
138 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
136 | PlayerEngine_Send (player); |
139 | PlayerEngine_Send (player); |
137 | 140 | ||
138 | // close the pipe handles |
141 | // close the pipe handles |
139 | if (hChessEngineStdinRd) |
142 | if (hChessEngineStdinRd) |
Line 271... | Line 274... | ||
271 | // has the game ended already ? |
274 | // has the game ended already ? |
272 | if (the_board.game_state > STATE_PLAYING) |
275 | if (the_board.game_state > STATE_PLAYING) |
273 | continue; // ignore all that the engine tells us. Game is over already. |
276 | continue; // ignore all that the engine tells us. Game is over already. |
274 | 277 | ||
275 | // is it a hint ? |
278 | // is it a hint ? |
276 | if ((move_string = wcsstr (line_buffer, options.engine.replystring_hint)) != NULL) |
279 | if ((move_string = wcsstr (line_buffer, options.engine.program_options.replystring_hint)) != NULL) |
277 | { |
280 | { |
278 | move_string += wcslen (options.engine.replystring_hint); // go to the parsable data |
281 | move_string += wcslen (options.engine.program_options.replystring_hint); // go to the parsable data |
279 | is_hint = true; |
282 | is_hint = true; |
280 | } |
283 | } |
281 | 284 | ||
282 | // else is it a normal move ? |
285 | // else is it a normal move ? |
283 | else if ((move_string = wcsstr (line_buffer, options.engine.replystring_move)) != NULL) |
286 | else if ((move_string = wcsstr (line_buffer, options.engine.program_options.replystring_move)) != NULL) |
284 | { |
287 | { |
285 | move_string += wcslen (options.engine.replystring_move); // go to the parsable data |
288 | move_string += wcslen (options.engine.program_options.replystring_move); // go to the parsable data |
286 | is_hint = false; |
289 | is_hint = false; |
287 | } |
290 | } |
288 | 291 | ||
289 | // else it's any other sort of line |
292 | // else it's any other sort of line |
290 | else |
293 | else |
Line 309... | Line 312... | ||
309 | 312 | ||
310 | // is it NOT a hint, are blunders allowed, should we do one now AND can we do one now ? |
313 | // is it NOT a hint, are blunders allowed, should we do one now AND can we do one now ? |
311 | if (!is_hint && (options.engine.blunder_chances > 0) && (rand () % 100 < options.engine.blunder_chances) |
314 | if (!is_hint && (options.engine.blunder_chances > 0) && (rand () % 100 < options.engine.blunder_chances) |
312 | && Move_FindRandomMove (&the_board.moves[the_board.move_count - 1], player->color, &move)) |
315 | && Move_FindRandomMove (&the_board.moves[the_board.move_count - 1], player->color, &move)) |
313 | { |
316 | { |
314 | Player_SendBuffer_Add (player, 1000, options.engine.command_force, Move_BuildString (&move)); // send the blunderous move to the engine |
317 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_force, Move_BuildString (&move)); // send the blunderous move to the engine |
315 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
318 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
316 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
319 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
317 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
320 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
318 | Debug_Log (L"===Discarding engine move, forcing a blunderous move (%s) instead===\n", Move_BuildString (&move)); // blunder |
321 | Debug_Log (L"===Discarding engine move, forcing a blunderous move (%s) instead===\n", Move_BuildString (&move)); // blunder |
319 | } |
322 | } |
Line 363... | Line 366... | ||
363 | if (the_board.was_setup) |
366 | if (the_board.was_setup) |
364 | { |
367 | { |
365 | Debug_Log (L"===Got board setup notification from interface===\n"); |
368 | Debug_Log (L"===Got board setup notification from interface===\n"); |
366 | 369 | ||
367 | // send a new game command to the chess engine |
370 | // send a new game command to the chess engine |
368 | Player_SendBuffer_Add (player, 1000, options.engine.command_new); |
371 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_new); |
369 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
372 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
370 | 373 | ||
371 | // just set up the board from its Forsyth-Edwards notation |
374 | // just set up the board from its Forsyth-Edwards notation |
372 | Debug_Log (L"===setting up board using FEN string===\n"); |
375 | Debug_Log (L"===setting up board using FEN string===\n"); |
373 | 376 | ||
374 | // instruct it about its allowed search depth BEFORE each table set (this ensures engine will be "ready" to handle the command) |
377 | // instruct it about its allowed search depth BEFORE each table set (this ensures engine will be "ready" to handle the command) |
375 | // then get the current game state in FEN format and feed it to the engine |
378 | // then get the current game state in FEN format and feed it to the engine |
376 | Player_SendBuffer_Add (player, 1000, options.engine.command_sd, options.engine.depth); |
379 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_sd, options.engine.depth); |
377 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
380 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
378 | Player_SendBuffer_Add (player, 1000, options.engine.command_setboard, the_board.moves[the_board.move_count - 1].fen_string); |
381 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_setboard, the_board.moves[the_board.move_count - 1].fen_string); |
379 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
382 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
380 | 383 | ||
381 | // and reset current obstinacy |
384 | // and reset current obstinacy |
382 | current_obstinacy = 0; |
385 | current_obstinacy = 0; |
383 | 386 | ||
Line 387... | Line 390... | ||
387 | 390 | ||
388 | // have we been notified that players are swapping colors ? (N.B. when this happens in human vs. computer mode, it's always that the human player is *GIVING* his turn) |
391 | // have we been notified that players are swapping colors ? (N.B. when this happens in human vs. computer mode, it's always that the human player is *GIVING* his turn) |
389 | if (the_board.want_playerswap) |
392 | if (the_board.want_playerswap) |
390 | { |
393 | { |
391 | Debug_Log (L"===Got player SWAP notification from interface===\n"); |
394 | Debug_Log (L"===Got player SWAP notification from interface===\n"); |
392 | Player_SendBuffer_Add (player, 1000, options.engine.command_go); // tell engine it's now the current player |
395 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_go); // tell engine it's now the current player |
393 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
396 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
394 | } |
397 | } |
395 | 398 | ||
396 | // have we been notified that the current player just changed ? |
399 | // have we been notified that the current player just changed ? |
397 | if (the_board.has_playerchanged) |
400 | if (the_board.has_playerchanged) |
Line 408... | Line 411... | ||
408 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
411 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
409 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
412 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
410 | 413 | ||
411 | // instruct it about its allowed search depth BEFORE each move (this ensures engine will be "ready" to handle the command) |
414 | // instruct it about its allowed search depth BEFORE each move (this ensures engine will be "ready" to handle the command) |
412 | // then build the move string, and send the move string to the engine |
415 | // then build the move string, and send the move string to the engine |
413 | Player_SendBuffer_Add (player, 1000, options.engine.command_sd, options.engine.depth); |
416 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_sd, options.engine.depth); |
414 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
417 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
415 | Player_SendBuffer_Add (player, 1000, Move_BuildString (&the_board.moves[the_board.move_count - 1])); |
418 | Player_SendBuffer_Add (player, 1000, Move_BuildString (&the_board.moves[the_board.move_count - 1])); |
416 | Player_SendBuffer_Add (player, 1000, L"\n"); // end the send buffer with a carriage return |
419 | Player_SendBuffer_Add (player, 1000, L"\n"); // end the send buffer with a carriage return |
417 | } |
420 | } |
418 | 421 | ||
419 | // else game has not started yet, but it's our turn |
422 | // else game has not started yet, but it's our turn |
420 | else |
423 | else |
421 | { |
424 | { |
422 | Player_SendBuffer_Add (player, 1000, options.engine.command_go); // so let's start the game |
425 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_go); // so let's start the game |
423 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
426 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
424 | } |
427 | } |
425 | } |
428 | } |
426 | } |
429 | } |
427 | 430 | ||
Line 434... | Line 437... | ||
434 | // does our opponent want a hint ? |
437 | // does our opponent want a hint ? |
435 | if (current_player->wants_hint) |
438 | if (current_player->wants_hint) |
436 | { |
439 | { |
437 | current_player->wants_hint = false; // don't ask twice |
440 | current_player->wants_hint = false; // don't ask twice |
438 | Debug_Log (L"===Hint requested, asking engine for it===\n"); |
441 | Debug_Log (L"===Hint requested, asking engine for it===\n"); |
439 | Player_SendBuffer_Add (player, 1000, options.engine.command_hint); // ask for a hint |
442 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_hint); // ask for a hint |
440 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
443 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
441 | } |
444 | } |
442 | 445 | ||
443 | // does our opponent want to cancel a move ? |
446 | // does our opponent want to cancel a move ? |
444 | if (current_player->wants_cancel) |
447 | if (current_player->wants_cancel) |
Line 454... | Line 457... | ||
454 | // just set up the board from its Forsyth-Edwards notation |
457 | // just set up the board from its Forsyth-Edwards notation |
455 | Debug_Log (L"===setting up board using FEN string===\n"); |
458 | Debug_Log (L"===setting up board using FEN string===\n"); |
456 | 459 | ||
457 | // instruct it about its allowed search depth BEFORE each table set (this ensures engine will be "ready" to handle the command) |
460 | // instruct it about its allowed search depth BEFORE each table set (this ensures engine will be "ready" to handle the command) |
458 | // then get the current game state in FEN format and feed it to the engine |
461 | // then get the current game state in FEN format and feed it to the engine |
459 | Player_SendBuffer_Add (player, 1000, options.engine.command_sd, options.engine.depth); |
462 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_sd, options.engine.depth); |
460 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
463 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
461 | Player_SendBuffer_Add (player, 1000, options.engine.command_setboard, the_board.moves[the_board.move_count - 1].fen_string); |
464 | Player_SendBuffer_Add (player, 1000, options.engine.program_options.command_setboard, the_board.moves[the_board.move_count - 1].fen_string); |
462 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
465 | Player_SendBuffer_Add (player, 1000, L"\n"); // since the format string was read from the options, don't forget to end it with a carriage return |
463 | 466 | ||
464 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
467 | if (wcscmp (options.engine.program, L"Crafty") == 0) |
465 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
468 | Player_SendBuffer_Add (player, 1000, L"disp\n"); |
466 | 469 |