1 #include "chess.h"
2 #include "data.h"
3 /* last modified 08/03/16 */
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  */
ResignOrDraw(TREE * RESTRICT tree,int value)20 void ResignOrDraw(TREE * RESTRICT tree, int value) {
21   int v, result = 0;
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 
112       strcpy(announce, "./speak ");
113       strcat(announce, "Resign");
114       v = system(announce);
115       if (v <= 0)
116         perror("ResignOrDraw() system() error: ");
117     }
118     if (crafty_is_white) {
119       Print(4095, "0-1 {White resigns}\n");
120       strcpy(pgn_result, "0-1");
121     } else {
122       Print(4095, "1-0 {Black resigns}\n");
123       strcpy(pgn_result, "1-0");
124     }
125   }
126   if (offer_draws && result == 2) {
127     draw_offered = 1;
128     if (!xboard) {
129       Print(1, "\nI offer a draw.\n\n");
130       if (audible_alarm)
131         printf("%c", audible_alarm);
132       if (speech) {
133         char announce[128];
134 
135         strcpy(announce, "./speak ");
136         strcat(announce, "Drawoffer");
137         v = system(announce);
138         if (v <= 0)
139           perror("ResignOrDraw() system() error: ");
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 }
148