Subversion Repositories Games.Chess Giants

Rev

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") != NULL) || (wcsistr (options.engine.name, L"GNU Chess") != NULL))
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