~ubuntu-branches/ubuntu/gutsy/grhino/gutsy

« back to all changes in this revision

Viewing changes to gtp-rhino.cc

  • Committer: Bazaar Package Importer
  • Author(s): Bart Martens
  • Date: 2007-04-02 20:38:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070402203809-fxyqqtkhj9ou03dy
Tags: upstream-0.16.0
ImportĀ upstreamĀ versionĀ 0.16.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        gtp-rhino.cc    GRhino GTP Frontend
 
3
        Copyright (c) 2005, 2006 Kriang Lerdsuwanakij
 
4
        email:          lerdsuwa@users.sourceforge.net
 
5
 
 
6
        This program is free software; you can redistribute it and/or modify
 
7
        it under the terms of the GNU General Public License as published by
 
8
        the Free Software Foundation; either version 2 of the License, or
 
9
        (at your option) any later version.
 
10
 
 
11
        This program is distributed in the hope that it will be useful,
 
12
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
        GNU General Public License for more details.
 
15
 
 
16
        You should have received a copy of the GNU General Public License
 
17
        along with this program; if not, write to the Free Software
 
18
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
*/
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include <pthread.h>
 
24
 
 
25
#include <pwd.h>
 
26
#include <sys/types.h>
 
27
#include <time.h>
 
28
#include <sys/time.h>
 
29
 
 
30
#include <exception>
 
31
#include <stdexcept>
 
32
#include <fstream>
 
33
#include <sstream>
 
34
#include <iomanip>
 
35
#include <string>
 
36
#include <deque>
 
37
#include <vector>
 
38
#include <sstream>
 
39
 
 
40
#include "board.h"
 
41
#include "hash.h"
 
42
#include "alphabeta.h"
 
43
#include "opening.h"
 
44
#include "pattern.h"
 
45
#include "parity.h"
 
46
#include "book.h"
 
47
#include "game.h"
 
48
#include "randboard.h"
 
49
#include "load.h"
 
50
#include "rand.h"
 
51
#include "boardio.h"
 
52
#include "gtp.h"
 
53
 
 
54
#include "gtstream.h"
 
55
 
 
56
// Grab version number in VERSION variable
 
57
#undef VERSION
 
58
char *
 
59
#include "scripts/version"
 
60
;
 
61
 
 
62
#ifdef _
 
63
#undef _
 
64
#endif
 
65
 
 
66
#ifdef N_
 
67
#undef N_
 
68
#endif
 
69
 
 
70
#include <libintl.h>
 
71
#define _(x) gettext(x)
 
72
#define N_(x) x
 
73
 
 
74
const char *prog_name = "gtp-rhino";
 
75
const char *prog_ver = VERSION;
 
76
 
 
77
int     randomness;
 
78
double  komi;
 
79
bool    game_logged;
 
80
bool    is_log;
 
81
 
 
82
unsigned        main_time = 0;
 
83
unsigned        byo_yomi_time = 1;
 
84
unsigned        byo_yomi_stones = 0;
 
85
 
 
86
bool            use_byo_yomi = false;
 
87
unsigned        time_left_black;
 
88
unsigned        stone_left_black;
 
89
unsigned        time_left_white;
 
90
unsigned        stone_left_white;
 
91
 
 
92
// Implementation status (GTP version 2 draft 2)
 
93
//      2.1 done        2.2 done        2.3 done        2.4 done
 
94
//      2.5 done        2.6 done        2.7 done        2.8 done
 
95
//      2.9 done        2.10 done       2.11 N/A        2.12 done
 
96
//      2.13 done       2.14 done
 
97
//      3.1 done        3.2 done        3.3 done        3.4 done
 
98
//      3.5 done        3.6 done
 
99
//      4.1 N/A         4.2             4.3 done
 
100
//      5.1             5.2 done        5.3 done
 
101
//      6.1 done        6.2             6.3
 
102
 
 
103
void    gtp_new_game(const byte_board_info *b = 0, int color = BLACK)
 
104
{
 
105
        eval_new_game();
 
106
        if (!b)
 
107
                new_game(cur_game_info);
 
108
        else
 
109
                new_game(cur_game_info, *b, color);
 
110
        time_player = 0;
 
111
        game_logged = false;
 
112
 
 
113
        use_byo_yomi = false;
 
114
        time_left_black = main_time;
 
115
        time_left_white = main_time;
 
116
}
 
117
 
 
118
void    gtp_maybe_log_game()
 
119
{
 
120
        if (!cur_game_info.is_game_play() && !game_logged) {
 
121
                game_logged = true;
 
122
                log_history("grhino.log", "player", "player");
 
123
        }
 
124
}
 
125
 
 
126
typedef void (*gtp_func)(const std::string &, size_t i, bool has_id, unsigned id);
 
127
 
 
128
struct gtp_command {
 
129
        const char      *command;
 
130
        gtp_func        func;
 
131
};
 
132
 
 
133
extern gtp_command gtp_commands[];
 
134
 
 
135
void    gtpfunc_protocol_version(const std::string &/*str*/, size_t /*i*/,
 
136
                                 bool has_id, unsigned id)
 
137
{
 
138
        output_response("2", has_id, id);
 
139
}
 
140
 
 
141
void    gtpfunc_name(const std::string &/*str*/, size_t /*i*/,
 
142
                     bool has_id, unsigned id)
 
143
{
 
144
        output_response("GTP GRhino", has_id, id);
 
145
}
 
146
 
 
147
void    gtpfunc_version(const std::string &/*str*/, size_t /*i*/,
 
148
                        bool has_id, unsigned id)
 
149
{
 
150
        output_response(VERSION, has_id, id);
 
151
}
 
152
 
 
153
void    gtpfunc_known_command(const std::string &str, size_t i,
 
154
                              bool has_id, unsigned id)
 
155
{
 
156
        i = skip_space(str, i);
 
157
        if (i == str.size())
 
158
                output_response("false", has_id, id);
 
159
        else {
 
160
                size_t j = skip_non_space(str, i);
 
161
                int k;
 
162
                for (k = 0 ; gtp_commands[k].command; ++k) {
 
163
                        if (!str.compare(i, j-i, gtp_commands[k].command))
 
164
                                break;
 
165
                }
 
166
                if (gtp_commands[k].command)
 
167
                        output_response("true", has_id, id);
 
168
                else
 
169
                        output_response("false", has_id, id);
 
170
        }
 
171
}
 
172
 
 
173
void    gtpfunc_list_commands(const std::string &/*str*/, size_t /*i*/,
 
174
                              bool has_id, unsigned id)
 
175
{
 
176
        std::string output;
 
177
        for (int k = 0 ; gtp_commands[k].command; ++k) {
 
178
                if (k != 0)
 
179
                        output += '\n';
 
180
                output += gtp_commands[k].command;
 
181
        }
 
182
        output_response(output, has_id, id);
 
183
}
 
184
 
 
185
void    gtpfunc_quit(const std::string &/*str*/, size_t /*i*/,
 
186
                     bool has_id, unsigned id)
 
187
{
 
188
        output_response("", has_id, id);
 
189
        throw command_quit();
 
190
}
 
191
 
 
192
void    gtpfunc_boardsize(const std::string &str, size_t i,
 
193
                           bool has_id, unsigned id)
 
194
{
 
195
        i = skip_space(str, i);
 
196
        throw_syntax_error_if_end_of_line(str, i);
 
197
 
 
198
        unsigned num;
 
199
        i = read_unsigned(str, i, num);
 
200
        throw_if_extra_argument(str, i);
 
201
        gtp_new_game();
 
202
        if (num != 8)
 
203
                output_error("unacceptable size", has_id, id);
 
204
        else
 
205
                output_response("", has_id, id);
 
206
}
 
207
 
 
208
void    gtpfunc_clear_board(const std::string &/*str*/, size_t /*i*/,
 
209
                            bool has_id, unsigned id)
 
210
{
 
211
        gtp_new_game();
 
212
        output_response("", has_id, id);
 
213
}
 
214
 
 
215
void    gtpfunc_komi(const std::string &str, size_t i,
 
216
                     bool has_id, unsigned id)
 
217
{
 
218
        i = skip_space(str, i);
 
219
        throw_syntax_error_if_end_of_line(str, i);
 
220
        i = read_float(str, i, komi);
 
221
        throw_if_extra_argument(str, i);
 
222
        output_response("", has_id, id);
 
223
}
 
224
 
 
225
void    gtpfunc_play(const std::string &str, size_t i,
 
226
                     bool has_id, unsigned id)
 
227
{
 
228
        i = skip_space(str, i);
 
229
        throw_syntax_error_if_end_of_line(str, i);
 
230
 
 
231
        int     color;
 
232
        i = read_color(str, i, color);
 
233
 
 
234
        i = skip_space(str, i);
 
235
        throw_syntax_error_if_end_of_line(str, i);
 
236
 
 
237
        int     row, col, pos;
 
238
        size_t j = skip_non_space(str, i);
 
239
        if (j-i != 2)
 
240
                throw syntax_error();
 
241
        if (str[i] >= 'A' && str[i] <= 'H')
 
242
                col = str[i] - 'A';
 
243
        else if (str[i] >= 'a' && str[i] <= 'h')
 
244
                col = str[i] - 'a';
 
245
        else
 
246
                throw syntax_error();
 
247
 
 
248
        if (str[i+1] >= '1' && str[i+1] <= '8')
 
249
                row = str[i+1] - '1';
 
250
        else
 
251
                throw syntax_error();
 
252
 
 
253
        throw_if_extra_argument(str, j);
 
254
 
 
255
        pos = xy_to_pos(col, row);
 
256
 
 
257
        if (color == cur_game_info.get_player()
 
258
            && cur_game_info.board_ptr->can_play(color, pos)) {
 
259
                // FIXME: Handle time
 
260
                cur_game_info.place_piece(pos, time_player);
 
261
                time_player = 0;
 
262
                gtp_maybe_log_game();
 
263
                output_response("", has_id, id);
 
264
        }
 
265
        else
 
266
                output_error("illegal move", has_id, id);
 
267
}
 
268
 
 
269
void    gtpfunc_genmove(const std::string &str, size_t i,
 
270
                        bool has_id, unsigned id)
 
271
{
 
272
        i = skip_space(str, i);
 
273
        throw_syntax_error_if_end_of_line(str, i);
 
274
 
 
275
        int     color;
 
276
        i = read_color(str, i, color);
 
277
 
 
278
        if (cur_game_info.is_game_play()
 
279
            && color == cur_game_info.get_player()) {
 
280
                int pos = get_computer_move (komi);
 
281
                // FIXME: Handle time
 
282
                cur_game_info.place_piece(pos, time_player);
 
283
                time_player = 0;
 
284
                gtp_maybe_log_game();
 
285
 
 
286
                std::string output;
 
287
                output += pos_to_x(pos) + 'A';
 
288
                output += pos_to_y(pos) + '1';
 
289
                output_response(output, has_id, id);
 
290
        }
 
291
        else
 
292
                output_response("pass", has_id, id);
 
293
}
 
294
 
 
295
void    gtpfunc_reg_genmove(const std::string &str, size_t i,
 
296
                            bool has_id, unsigned id)
 
297
{
 
298
        i = skip_space(str, i);
 
299
        throw_syntax_error_if_end_of_line(str, i);
 
300
 
 
301
        int     color;
 
302
        i = read_color(str, i, color);
 
303
 
 
304
        if (cur_game_info.is_game_play()
 
305
            && color == cur_game_info.get_player()) {
 
306
                random_off();
 
307
                int pos = get_computer_move (komi);
 
308
                random_on();
 
309
 
 
310
                std::string output;
 
311
                output += pos_to_x(pos) + 'A';
 
312
                output += pos_to_y(pos) + '1';
 
313
                output_response(output, has_id, id);
 
314
        }
 
315
        else
 
316
                output_response("pass", has_id, id);
 
317
}
 
318
 
 
319
void    gtpfunc_auto_play(const std::string &/*str*/, size_t /*i*/,
 
320
                        bool has_id, unsigned id)
 
321
{
 
322
        while (cur_game_info.is_game_play()) {
 
323
                int pos = get_computer_move (komi);
 
324
                // FIXME: Handle time
 
325
                cur_game_info.place_piece(pos, time_player);
 
326
        }
 
327
        gtp_maybe_log_game();
 
328
        output_response("", has_id, id);
 
329
}
 
330
 
 
331
void    gtpfunc_time_settings(const std::string &str, size_t i,
 
332
                              bool has_id, unsigned id)
 
333
{
 
334
        i = skip_space(str, i);
 
335
        throw_syntax_error_if_end_of_line(str, i);
 
336
 
 
337
        unsigned m, b, s;
 
338
 
 
339
        i = read_unsigned(str, i, m);
 
340
        i = skip_space(str, i);
 
341
        throw_syntax_error_if_end_of_line(str, i);
 
342
 
 
343
        i = read_unsigned(str, i, b);
 
344
        i = skip_space(str, i);
 
345
        throw_syntax_error_if_end_of_line(str, i);
 
346
 
 
347
        i = read_unsigned(str, i, s);
 
348
        throw_if_extra_argument(str, i);
 
349
 
 
350
        main_time = m;
 
351
        byo_yomi_time = b;
 
352
        byo_yomi_stones = s;
 
353
 
 
354
        use_byo_yomi = false;
 
355
        time_left_black = main_time;
 
356
        time_left_white = main_time;
 
357
        time_player = 0;
 
358
 
 
359
        output_response("", has_id, id);
 
360
}
 
361
 
 
362
void    gtpfunc_time_left(const std::string &str, size_t i,
 
363
                          bool has_id, unsigned id)
 
364
{
 
365
        i = skip_space(str, i);
 
366
        throw_syntax_error_if_end_of_line(str, i);
 
367
 
 
368
        int     color;
 
369
        i = read_color(str, i, color);
 
370
 
 
371
        i = skip_space(str, i);
 
372
        throw_syntax_error_if_end_of_line(str, i);
 
373
 
 
374
        unsigned t, s;
 
375
 
 
376
        i = read_unsigned(str, i, t);
 
377
        i = skip_space(str, i);
 
378
        throw_syntax_error_if_end_of_line(str, i);
 
379
 
 
380
        i = read_unsigned(str, i, s);
 
381
        throw_if_extra_argument(str, i);
 
382
 
 
383
        if (color == BLACK) {
 
384
                time_left_black = t;
 
385
                stone_left_black = s;
 
386
        }
 
387
        else {
 
388
                time_left_white = t;
 
389
                stone_left_white = s;
 
390
        }
 
391
        time_player = 0;
 
392
 
 
393
        output_response("", has_id, id);
 
394
}
 
395
 
 
396
void    gtpfunc_final_score(const std::string &/*str*/, size_t /*i*/,
 
397
                            bool has_id, unsigned id)
 
398
{
 
399
        if (cur_game_info.is_game_play())
 
400
                output_error("cannot score", has_id, id);
 
401
        else {
 
402
                int     black_score = cur_game_info.board_ptr->board_black_score();
 
403
                int     white_score = cur_game_info.board_ptr->board_white_score();
 
404
 
 
405
                switch (cur_game_info.get_game_result()) {
 
406
                        case game_info::game_result_end:
 
407
                                adjust_score(black_score, white_score);
 
408
                                break;
 
409
                        case game_info::game_result_timeout_black:
 
410
                                black_score = 0;
 
411
                                white_score = 64;
 
412
                                break;
 
413
                        case game_info::game_result_timeout_white:
 
414
                                black_score = 64;
 
415
                                white_score = 0;
 
416
                                break;
 
417
                        case game_info::game_result_resign_black:
 
418
                                black_score = 0;
 
419
                                white_score = 64;
 
420
                                break;
 
421
                        case game_info::game_result_resign_white:
 
422
                                black_score = 64;
 
423
                                white_score = 0;
 
424
                                break;
 
425
                }
 
426
 
 
427
                std::ostringstream os;
 
428
                double diff_score = black_score - white_score - komi;
 
429
                if (diff_score > 0)
 
430
                        os << "B+" << diff_score;
 
431
                else if (diff_score < 0)
 
432
                        os << "W+" << (-diff_score);
 
433
                else
 
434
                        os << '0';
 
435
                output_response(os.str(), has_id, id);
 
436
        }
 
437
}
 
438
 
 
439
void    gtpfunc_showboard(const std::string &/*str*/, size_t /*i*/,
 
440
                          bool has_id, unsigned id)
 
441
{
 
442
        std::ostringstream os;
 
443
 
 
444
        if (cur_game_info.is_game_play()) {
 
445
                os << "Next move: ";
 
446
                if (cur_game_info.get_player() == BLACK)
 
447
                        os << "Black";
 
448
                else
 
449
                        os << "White";
 
450
        }
 
451
        else {
 
452
                switch (cur_game_info.get_game_result()) {
 
453
                        case game_info::game_result_end:
 
454
                                os << "Game ended";
 
455
                                break;
 
456
                        case game_info::game_result_timeout_black:
 
457
                                os << "Black ran out of time";
 
458
                                break;
 
459
                        case game_info::game_result_timeout_white:
 
460
                                os << "White ran out of time";
 
461
                                break;
 
462
                        case game_info::game_result_resign_black:
 
463
                                os << "Black resigned";
 
464
                                break;
 
465
                        case game_info::game_result_resign_white:
 
466
                                os << "White resigned";
 
467
                                break;
 
468
                }
 
469
        }
 
470
        os << '\n';
 
471
        print_board(os, cur_game_info.board_ptr, 2);
 
472
 
 
473
        output_response(os.str(), has_id, id);
 
474
}
 
475
 
 
476
void    gtpfunc_undo(const std::string &/*str*/, size_t /*i*/,
 
477
                     bool has_id, unsigned id)
 
478
{
 
479
        if (cur_game_info.is_undoable()) {
 
480
                cur_game_info.undo();
 
481
                game_logged = false;
 
482
                output_response("", has_id, id);
 
483
        }
 
484
        else
 
485
                output_error("cannot undo", has_id, id);
 
486
}
 
487
 
 
488
void    gtpfunc_set_game(const std::string &str, size_t i,
 
489
                         bool has_id, unsigned id)
 
490
{
 
491
        i = skip_space(str, i);
 
492
        throw_syntax_error_if_end_of_line(str, i);
 
493
 
 
494
        size_t j = skip_non_space(str, i);
 
495
        if (!str.compare(i, j-i, "Othello"))
 
496
                output_response("", has_id, id);
 
497
        else
 
498
                output_error("unsupported game", has_id, id);
 
499
}
 
500
 
 
501
void    gtpfunc_list_games(const std::string &/*str*/, size_t /*i*/,
 
502
                           bool has_id, unsigned id)
 
503
{
 
504
        output_response("Othello", has_id, id);
 
505
}
 
506
 
 
507
void    gtpfunc_setup_board(const std::string &str, size_t i,
 
508
                            bool has_id, unsigned id)
 
509
{
 
510
        i = skip_space(str, i);
 
511
        throw_syntax_error_if_end_of_line(str, i);
 
512
 
 
513
        size_t j = skip_non_space(str, i);
 
514
        if (j-i != 64)
 
515
                throw syntax_error();
 
516
        j = skip_space(str, j);
 
517
        int     color = BLACK;
 
518
        if (j != str.size()) {
 
519
                                // Optional player with first move
 
520
                size_t jj = skip_non_space(str, j);
 
521
                throw_if_extra_argument(str, jj);
 
522
                if (jj-j == 1) {
 
523
                        switch (str[j]) {
 
524
                                case 'O':
 
525
                                case 'o':
 
526
                                case '0':
 
527
                                case 'W':
 
528
                                case 'w':
 
529
                                        color = WHITE;
 
530
                                        break;
 
531
                                case '@':
 
532
                                case '*':
 
533
                                case 'X':
 
534
                                case 'x':
 
535
                                case 'B':
 
536
                                case 'b':
 
537
                                        // Default is already black
 
538
                                        break;
 
539
                                default:
 
540
                                        throw syntax_error();
 
541
                        }
 
542
                }
 
543
                else
 
544
                        read_color(str, j, color);
 
545
        }
 
546
 
 
547
        byte_board_type t;
 
548
        int num_pieces = 0;
 
549
        for (int k = 0; k < 64; ++k) {
 
550
                piece_type p;
 
551
                switch (str[i+k]) {
 
552
                        case '_':
 
553
                        case '-':
 
554
                        case '.':
 
555
                                p = EMPTY;
 
556
                                break;
 
557
                        case 'O':
 
558
                        case 'o':
 
559
                        case '0':
 
560
                                p = WHITE;
 
561
                                num_pieces++;
 
562
                                break;
 
563
                        case '@':
 
564
                        case '*':
 
565
                        case 'X':
 
566
                        case 'x':
 
567
                                p = BLACK;
 
568
                                num_pieces++;
 
569
                                break;
 
570
                        default:
 
571
                                throw syntax_error();
 
572
                }
 
573
                t[k] = p;
 
574
        }
 
575
        if (num_pieces < 4)
 
576
                throw syntax_error();
 
577
 
 
578
        byte_board_info b(&t);
 
579
        gtp_new_game(&b, color);
 
580
        output_response("", has_id, id);
 
581
}
 
582
 
 
583
void    gtpfunc_show_history(const std::string &/*str*/, size_t /*i*/,
 
584
                             bool has_id, unsigned id)
 
585
{
 
586
        std::string output;
 
587
        for (int i = 0; i < cur_game_info.num_history-1; ++i) {
 
588
                int pos = cur_game_info.move_history[i];
 
589
                if (i != 0) {
 
590
                        output += ' ';
 
591
                        if (cur_game_info.player_history[i-1]
 
592
                            == cur_game_info.player_history[i])
 
593
                                output += "pass ";
 
594
                }
 
595
                else {
 
596
                        if (cur_game_info.first_play_is_pass)
 
597
                                output += "pass ";
 
598
                }
 
599
 
 
600
                output += pos_to_x(pos) + 'A';
 
601
                output += pos_to_y(pos) + '1';
 
602
        }
 
603
        output_response(output, has_id, id);
 
604
}
 
605
 
 
606
gtp_command gtp_commands[] = {
 
607
        { "protocol_version", gtpfunc_protocol_version },
 
608
        { "name", gtpfunc_name },
 
609
        { "version", gtpfunc_version },
 
610
        { "known_command", gtpfunc_known_command },
 
611
        { "list_commands", gtpfunc_list_commands },
 
612
        { "quit", gtpfunc_quit },
 
613
        { "boardsize", gtpfunc_boardsize },
 
614
        { "clear_board", gtpfunc_clear_board },
 
615
        { "komi", gtpfunc_komi },
 
616
                                        // Not supported: fixed_handicap,
 
617
                                        // place_free_handicap,
 
618
                                        // set_free_handicap
 
619
        { "play", gtpfunc_play },
 
620
        { "genmove", gtpfunc_genmove },
 
621
        { "undo", gtpfunc_undo },
 
622
                                        // Not supported:
 
623
                                        // final_status_list, load_sgf
 
624
        { "time_settings", gtpfunc_time_settings },
 
625
        { "time_left", gtpfunc_time_left },
 
626
        { "final_score", gtpfunc_final_score },
 
627
        { "showboard", gtpfunc_showboard },
 
628
        { "reg_genmove", gtpfunc_reg_genmove },
 
629
 
 
630
                                        // Othello extension
 
631
        { "set_game", gtpfunc_set_game },
 
632
        { "list_games", gtpfunc_list_games },
 
633
 
 
634
                                        // GTP-Rhino extension
 
635
        { "grhino-auto_play", gtpfunc_auto_play },
 
636
        { "grhino-setup_board", gtpfunc_setup_board },
 
637
        { "grhino-show_history", gtpfunc_show_history },
 
638
        { 0, 0 }
 
639
};
 
640
 
 
641
void    gtp_process_loop()
 
642
{
 
643
        std::string     str;
 
644
 
 
645
        bool            has_id;
 
646
        unsigned        id;
 
647
        size_t          i;
 
648
 
 
649
        for ( ; ; ) {
 
650
                try {
 
651
                        input_line(str);
 
652
                        i = parse_id(str, has_id, id);
 
653
                        i = skip_space(str, i);
 
654
                        throw_command_error_if_end_of_line(str, i);
 
655
 
 
656
                        size_t j = skip_non_space(str, i);
 
657
                        int k;
 
658
                        for (k = 0; gtp_commands[k].command; ++k) {
 
659
                                if (!str.compare(i, j-i, gtp_commands[k].command)) {
 
660
                                        gtp_commands[k].func(str, j, has_id, id);
 
661
                                        break;
 
662
                                }
 
663
                        }
 
664
                        if (!gtp_commands[k].command)
 
665
                                throw command_error();
 
666
                }
 
667
                catch (id_error &) {
 
668
                        output_error("unknown command", false, 0);
 
669
                }
 
670
                catch (command_error &) {
 
671
                        output_error("unknown command", has_id, id);
 
672
                }
 
673
                catch (syntax_error &) {
 
674
                        output_error("syntax error", has_id, id);
 
675
                }
 
676
                catch (command_quit &) {
 
677
                        return;
 
678
                }
 
679
                catch (io_error &) {
 
680
                        return;
 
681
                }
 
682
        }
 
683
}
 
684
 
 
685
void    set_level(int level)
 
686
{
 
687
        computer_level = level;
 
688
        current_level_info.midgame_depth
 
689
                = level_info[computer_level].midgame_depth;
 
690
        current_level_info.num_empty_winlossdraw
 
691
                = level_info[computer_level].num_empty_winlossdraw;
 
692
        current_level_info.num_empty_exact
 
693
                = level_info[computer_level].num_empty_exact;
 
694
        set_midgame_depth(current_level_info.midgame_depth);
 
695
}
 
696
 
 
697
void    init()
 
698
{
 
699
        trans_table_init();
 
700
        set_max_hash_move(57);
 
701
 
 
702
        pattern_table_init();
 
703
        book_init();
 
704
        srand(time(NULL));
 
705
 
 
706
        set_level(1);                   // Default level
 
707
 
 
708
                                        // Default parameters
 
709
        randomness = 0;
 
710
        set_eval_random(randomness);
 
711
        opening_var = 2;
 
712
        set_book_random(opening_var);
 
713
        log_move = false;
 
714
        redo_ai_move = true;
 
715
        start_game_mode = START_GAME_INITIAL;
 
716
 
 
717
        is_log = false;
 
718
}
 
719
 
 
720
int     main_real(int argc, char *argv[])
 
721
{
 
722
                                        // Need to parse parameter
 
723
        if (argc > 1) {
 
724
                for (int i = 1; i < argc; ++i) {
 
725
                        std::string arg = argv[i];
 
726
                        unsigned u;
 
727
 
 
728
                        if (arg == "-h" || arg == "--help") {
 
729
                                std::cout << prog_name << ' ' << prog_ver << _(" - GTP Frontend for Rhino\n");
 
730
                                std::cout << _("(c) 2005 Kriang Lerdsuwanakij\n\n");
 
731
                                gtout(std::cout, _("Usage:   %$ [options]\n")) << prog_name;
 
732
                                std::cout << _("Available options:\n");
 
733
                                std::cout << _("     -b N, --book=N    Use open book variation N.  Allowed = 0..5 (means None..Very high).\n");
 
734
                                std::cout << _("                       Default = 2 (means Low)\n");
 
735
                                std::cout << _("     -e N, --end=N     Use perfect end game search depth N instead of default value for\n");
 
736
                                std::cout << _("                       level.  Allowed = 1..20.\n");
 
737
                                std::cout << _("     -h, --help        Display this help\n");
 
738
                                std::cout << _("     -l N, --level=N   Use AI level N.  Allowed = 1..5.  Default = 3\n");
 
739
                                std::cout << _("     --log             Log game to ~/grhino.log\n");
 
740
                                std::cout << _("     -m N, --mid=N     Use mid game search depth N instead of default value for level.\n");
 
741
                                std::cout << _("                       Allowed = 1..20\n");
 
742
                                std::cout << _("     -r N, --rand=N    Use randomness N in AI evaluator.  Allowed = 0..10.  Default = 0\n");
 
743
                                std::cout << _("     -v, --version     Display version number\n");
 
744
                                std::cout << _("     -w N, --win=N     Use winning move search depth N instead of default value for level.\n");
 
745
                                std::cout << _("                       Allowed = 1..20\n\n");
 
746
                                return 0;
 
747
                        }
 
748
                        else if (arg == "-v" || arg == "--version") {
 
749
                                std::cout << prog_name << ' ' << prog_ver << '\n';
 
750
                                return 0;
 
751
                        }
 
752
                        else if (process_unsigned_option(argc, argv, arg, i,
 
753
                                                         "-l", "--level",
 
754
                                                         1, 5, u)) {
 
755
                                set_level(u - 1);
 
756
                        }
 
757
                        else if (process_unsigned_option(argc, argv, arg, i,
 
758
                                                         "-m", "--mid",
 
759
                                                         1, 20, u)) {
 
760
                                current_level_info.midgame_depth = u;
 
761
                                set_midgame_depth(current_level_info.midgame_depth);
 
762
                        }
 
763
                        else if (process_unsigned_option(argc, argv, arg, i,
 
764
                                                         "-e", "--end",
 
765
                                                         1, 20, u)) {
 
766
                                current_level_info.num_empty_exact = u;
 
767
                                if (current_level_info.num_empty_winlossdraw
 
768
                                    < static_cast<int>(u))
 
769
                                        current_level_info.num_empty_winlossdraw = u;
 
770
                        }
 
771
                        else if (process_unsigned_option(argc, argv, arg, i,
 
772
                                                         "-w", "--win",
 
773
                                                         1, 20, u)) {
 
774
                                current_level_info.num_empty_winlossdraw = u;
 
775
                                if (current_level_info.num_empty_exact
 
776
                                    > static_cast<int>(u))
 
777
                                        current_level_info.num_empty_exact = u;
 
778
                        }
 
779
                        else if (process_unsigned_option(argc, argv, arg, i,
 
780
                                                         "-r", "--rand",
 
781
                                                         0, 10, u)) {
 
782
                                randomness = u;
 
783
                                set_eval_random(randomness);
 
784
                        }
 
785
                        else if (process_unsigned_option(argc, argv, arg, i,
 
786
                                                         "-b", "--book",
 
787
                                                         0, 5, u)) {
 
788
                                opening_var = u;
 
789
                                set_book_random(opening_var);
 
790
                        }
 
791
                        else if (arg == "--log")
 
792
                                is_log = true;
 
793
                        else {
 
794
                                gtstream bufstr;
 
795
                                gtout(bufstr, _("unknown option `%$\'")) <<  arg;
 
796
                                throw std::runtime_error(bufstr.str());
 
797
                        }
 
798
                }
 
799
        }
 
800
 
 
801
        try {
 
802
                gtp_new_game();
 
803
                gtp_process_loop();
 
804
        }
 
805
        catch (...) {
 
806
        }
 
807
 
 
808
        return 0;
 
809
}
 
810
 
 
811
int     main(int argc, char *argv[])
 
812
{
 
813
        try {
 
814
                init();
 
815
                return main_real(argc, argv);
 
816
        }
 
817
        catch (std::exception &e) {
 
818
                std::cout << std::flush;
 
819
                gtout(std::cerr, _("%$: %$\n")) << prog_name << e.what();
 
820
        }
 
821
        catch (const char *s) {
 
822
                std::cout << std::flush;
 
823
                gtout(std::cerr, _("%$: exception %$\n")) << prog_name << s;
 
824
        }
 
825
        catch (...) {
 
826
                std::cout << std::flush;
 
827
                gtout(std::cerr, _("%$: unknown exception\n")) << prog_name;
 
828
        }
 
829
        return 1;
 
830
}