Rev 108 | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" | 
| 2 | #include "data.h" | ||
| 154 | pmbaty | 3 | /* last modified 08/03/16 */ | 
| 33 | pmbaty | 4 | /* | 
| 5 |  ******************************************************************************* | ||
| 6 |  *                                                                             * | ||
| 7 |  *   ResignOrDraw() is used to determine if the program should either resign   * | ||
| 8 |  *   or offer a draw.  This decision is based on two criteria:  (1) current    * | ||
| 9 |  *   search evaluation and (2) time remaining on opponent's clock.             * | ||
| 10 |  *                                                                             * | ||
| 11 |  *   The evaluation returned by the last search must be less than the resign   * | ||
| 12 |  *   threshold to trigger the resign code, or else must be exactly equal to    * | ||
| 13 |  *   the draw score to trigger the draw code.                                  * | ||
| 14 |  *                                                                             * | ||
| 15 |  *   The opponent must have enough time to be able to win or draw the game if  * | ||
| 16 |  *   it were played out as well.                                               * | ||
| 17 |  *                                                                             * | ||
| 18 |  ******************************************************************************* | ||
| 19 |  */ | ||
| 20 | void ResignOrDraw(TREE * RESTRICT tree, int value) { | ||
| 108 | pmbaty | 21 | int v, result = 0; | 
| 33 | pmbaty | 22 | |
| 23 | /* | ||
| 24 |  ************************************************************ | ||
| 25 |  *                                                          * | ||
| 26 |  *  If the game is a technical draw, where there are no     * | ||
| 27 |  *  pawns and material is balanced, then offer a draw.      * | ||
| 28 |  *                                                          * | ||
| 29 |  ************************************************************ | ||
| 30 |  */ | ||
| 31 | if (Drawn(tree, value) == 1) | ||
| 32 | result = 2; | ||
| 33 | /* | ||
| 34 |  ************************************************************ | ||
| 35 |  *                                                          * | ||
| 36 |  *  First check to see if the increment is 2 seconds or     * | ||
| 37 |  *  more.  If so, then the game is being played slowly      * | ||
| 38 |  *  enough that a draw offer or resignation is worth        * | ||
| 39 |  *  consideration.  Otherwise, if the opponent has at least * | ||
| 40 |  *  30 seconds left, he can probably play the draw or win   * | ||
| 41 |  *  out.                                                    * | ||
| 42 |  *                                                          * | ||
| 43 |  *  If the value is below the resignation threshold, then   * | ||
| 44 |  *  Crafty should resign and get on to the next game. Note  * | ||
| 45 |  *  that it is necessary to have a bad score for            * | ||
| 46 |  *  <resign_count> moves in a row before resigning.         * | ||
| 47 |  *                                                          * | ||
| 48 |  *  Note that we don't resign for "deep mates" since we do  * | ||
| 49 |  *  not know if the opponent actually saw that result.  We  * | ||
| 50 |  *  play on until it becomes obvious he "sees it."          * | ||
| 51 |  *                                                          * | ||
| 52 |  ************************************************************ | ||
| 53 |  */ | ||
| 54 | if ((tc_increment > 200) || (tc_time_remaining[Flip(root_wtm)] >= 3000)) { | ||
| 55 | if (resign) { | ||
| 56 | if (value < -(MATE - 15)) { | ||
| 57 | if (++resign_counter >= resign_count) | ||
| 58 | result = 1; | ||
| 59 | } else if (value < -resign * 100 && value > -32000) { | ||
| 60 | if (++resign_counter >= resign_count) | ||
| 61 | result = 1; | ||
| 62 | } else | ||
| 63 | resign_counter = 0; | ||
| 64 |     } | ||
| 65 |   } | ||
| 66 | /* | ||
| 67 |  ************************************************************ | ||
| 68 |  *                                                          * | ||
| 69 |  *  If the value is almost equal to the draw score, then    * | ||
| 70 |  *  Crafty should offer the opponent a draw.  Note that it  * | ||
| 71 |  *  is necessary that the draw score occur on exactly       * | ||
| 72 |  *  <draw_count> moves in a row before making the offer.    * | ||
| 73 |  *  Note also that the draw offer will be repeated every    * | ||
| 74 |  *  <draw_count> moves so setting this value too low can    * | ||
| 75 |  *  make the program behave "obnoxiously."                  * | ||
| 76 |  *                                                          * | ||
| 77 |  ************************************************************ | ||
| 78 |  */ | ||
| 79 | if ((tc_increment > 200) || (tc_time_remaining[Flip(root_wtm)] >= 3000)) { | ||
| 80 | if (Abs(Abs(value) - Abs(DrawScore(game_wtm))) < 2 && | ||
| 81 | moves_out_of_book > 3) { | ||
| 82 | if (++draw_counter >= draw_count) { | ||
| 83 | draw_counter = 0; | ||
| 84 | result = 2; | ||
| 85 |       } | ||
| 86 | } else | ||
| 87 | draw_counter = 0; | ||
| 88 |   } | ||
| 89 | /* | ||
| 90 |  ************************************************************ | ||
| 91 |  *                                                          * | ||
| 92 |  *  Now print the draw offer or resignation if appropriate  * | ||
| 93 |  *  but be sure and do it in a form that ICC/FICS will      * | ||
| 94 |  *  understand if the "xboard" flag is set.                 * | ||
| 95 |  *                                                          * | ||
| 96 |  *  Note that we also use the "speak" facility to verbally  * | ||
| 97 |  *  offer draws or resign if the "speech" variable has been * | ||
| 98 |  *  set to 1 by entering "speech on".                       * | ||
| 99 |  *                                                          * | ||
| 100 |  ************************************************************ | ||
| 101 |  */ | ||
| 102 | if (result == 1) { | ||
| 103 | learn_value = (crafty_is_white) ? -300 : 300; | ||
| 104 | LearnBook(); | ||
| 105 | if (xboard) | ||
| 106 | Print(4095, "resign\n"); | ||
| 107 | if (audible_alarm) | ||
| 108 | printf("%c", audible_alarm); | ||
| 109 | if (speech) { | ||
| 110 | char announce[128]; | ||
| 111 | |||
| 108 | pmbaty | 112 | strcpy(announce, "./speak "); | 
| 113 | strcat(announce, "Resign"); | ||
| 114 | v = system(announce); | ||
| 115 | if (v <= 0) | ||
| 116 | perror("ResignOrDraw() system() error: "); | ||
| 33 | pmbaty | 117 |     } | 
| 118 | if (crafty_is_white) { | ||
| 119 | Print(4095, "0-1 {White resigns}\n"); | ||
| 108 | pmbaty | 120 | strcpy(pgn_result, "0-1"); | 
| 33 | pmbaty | 121 | } else { | 
| 122 | Print(4095, "1-0 {Black resigns}\n"); | ||
| 108 | pmbaty | 123 | strcpy(pgn_result, "1-0"); | 
| 33 | pmbaty | 124 |     } | 
| 125 |   } | ||
| 126 | if (offer_draws && result == 2) { | ||
| 127 | draw_offered = 1; | ||
| 128 | if (!xboard) { | ||
| 108 | pmbaty | 129 | Print(1, "\nI offer a draw.\n\n"); | 
| 33 | pmbaty | 130 | if (audible_alarm) | 
| 131 | printf("%c", audible_alarm); | ||
| 132 | if (speech) { | ||
| 133 | char announce[128]; | ||
| 134 | |||
| 108 | pmbaty | 135 | strcpy(announce, "./speak "); | 
| 136 | strcat(announce, "Drawoffer"); | ||
| 137 | v = system(announce); | ||
| 138 | if (v <= 0) | ||
| 139 | perror("ResignOrDraw() system() error: "); | ||
| 33 | pmbaty | 140 |       } | 
| 141 | } else if (xboard) | ||
| 142 | Print(4095, "offer draw\n"); | ||
| 143 |     else | ||
| 144 | Print(4095, "\n*draw\n"); | ||
| 145 | } else | ||
| 146 | draw_offered = 0; | ||
| 147 | } |