~vcs-imports-ii/gnubg/trunk

1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
1
/*
2
 * movefilter.c
3
 *
4
 * by Joern Thyssen <jthyssen@dk.ibm.com>, 2002
5
 *
6
 * This program is free software; you can redistribute it and/or modify
3944 by ace
*** empty log message ***
7
 * it under the terms of version 3 or later of the GNU General Public License as
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
8
 * published by the Free Software Foundation.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
5379 by mdpetch
Standardized the code formatting with indent -kr -l120 -fc1 -sc -nut -psl
19
 * $Id: gtkmovefilter.c,v 1.33 2013/06/16 02:16:15 mdpetch Exp $
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
20
 */
21
3940 by c_anthon
replace gtk_signal* with g_signal*
22
#include "config.h"
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "gtkgame.h"
29
#include "gtkmovefilter.h"
3682 by Superfly_Jon
Fixed modal dialog z order problems
30
#include "gtkwindows.h"
5050 by mdpetch
Work around deprecated GtkComboBox functionality.
31
#include "gtklocdefs.h"
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
32
33
typedef struct _movefilterwidget {
34
35
5379 by mdpetch
Standardized the code formatting with indent -kr -l120 -fc1 -sc -nut -psl
36
    movefilter *pmf;
37
38
    /* the menu with default settings */
39
40
    GtkWidget *pwOptionMenu;
41
42
    /* callback for the parent */
43
44
    GCallback pfChanged;
45
    gpointer userdata;
1933 by thyssen
Use Michael Depreli's set of predefined filters, and introduce 0 as an
46
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
47
} movefilterwidget;
48
49
50
typedef struct _movefiltersetupwidget {
51
5379 by mdpetch
Standardized the code formatting with indent -kr -l120 -fc1 -sc -nut -psl
52
    int *pfOK;
53
    movefilter *pmf;
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
54
5379 by mdpetch
Standardized the code formatting with indent -kr -l120 -fc1 -sc -nut -psl
55
    GtkAdjustment *aapadjAccept[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
56
    GtkAdjustment *aapadjExtra[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
57
    GtkAdjustment *aapadjThreshold[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
58
    GtkWidget *aapwA[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
59
    GtkWidget *aapwET[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
60
    GtkWidget *aapwT[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
61
    GtkWidget *aapwEnable[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
62
    GtkWidget *pwOptionMenu;
1833 by thyssen
Separate movefilters for evaluation, analysis, rollouts, and players.
63
64
} movefiltersetupwidget;
65
66
67
static void
5379 by mdpetch
Standardized the code formatting with indent -kr -l120 -fc1 -sc -nut -psl
68
MoveFilterSetupSetValues(movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES], const movefiltersetupwidget * pmfsw)
69
{
70
71
    int i, j;
72
    int f;
73
74
    for (i = 0; i < MAX_FILTER_PLIES; ++i)
75
        for (j = 0; j <= i; ++j) {
76
77
            gtk_adjustment_set_value(pmfsw->aapadjAccept[i][j], aamf[i][j].Accept >= 0 ? aamf[i][j].Accept : 0);
78
            gtk_adjustment_set_value(pmfsw->aapadjExtra[i][j], aamf[i][j].Accept >= 0 ? aamf[i][j].Extra : 0);
79
            gtk_adjustment_set_value(pmfsw->aapadjThreshold[i][j],
80
                                     (aamf[i][j].Accept >= 0 && aamf[i][j].Extra) ? aamf[i][j].Threshold : 0);
81
82
            f = aamf[i][j].Accept >= 0;
83
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwA[i][j]), f);
84
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwET[i][j]), f);
85
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pmfsw->aapwEnable[i][j]), f);
86
            f = f && aamf[i][j].Extra;
87
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwT[i][j]), f);
88
89
90
        }
91
92
}
93
94
95
96
static void
97
MoveFilterSetupGetValues(movefilter * pmf, const movefiltersetupwidget * pmfsw)
98
{
99
100
    int i, j;
101
    movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
102
    int f;
103
104
    memset(aamf, 0, sizeof(aamf));
105
106
    for (i = 0; i < MAX_FILTER_PLIES; ++i)
107
        for (j = 0; j <= i; ++j) {
108
109
            f = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pmfsw->aapwEnable[i][j]));
110
111
            aamf[i][j].Accept = f ? (int) gtk_adjustment_get_value(pmfsw->aapadjAccept[i][j]) : -1;
112
            aamf[i][j].Extra = (aamf[i][j].Accept >= 0) ? (int) gtk_adjustment_get_value(pmfsw->aapadjExtra[i][j]) : 0;
113
            aamf[i][j].Threshold = (aamf[i][j].Extra) ?
114
                (float) gtk_adjustment_get_value(pmfsw->aapadjThreshold[i][j]) : 0;
115
116
        }
117
118
    memcpy(pmf, aamf, sizeof(aamf));
119
120
}
121
122
123
static void
124
AcceptChanged(GtkWidget * UNUSED(pw), movefiltersetupwidget * pmfsw)
125
{
126
127
    int fFound;
128
    unsigned int i;
129
    movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
130
131
    /* see if current settings match a predefined one */
132
133
    fFound = FALSE;
134
135
    MoveFilterSetupGetValues(aamf[0], pmfsw);
136
137
    for (i = 0; i < NUM_MOVEFILTER_SETTINGS; ++i)
138
        if (equal_movefilters(aamf, aaamfMoveFilterSettings[i])) {
139
            gtk_combo_box_set_active(GTK_COMBO_BOX(pmfsw->pwOptionMenu), i);
140
            fFound = TRUE;
141
            break;
142
        }
143
144
    if (!fFound)
145
        gtk_combo_box_set_active(GTK_COMBO_BOX(pmfsw->pwOptionMenu), NUM_MOVEFILTER_SETTINGS);
146
}
147
148
149
static void
150
EnableToggled(GtkWidget * pw, movefiltersetupwidget * pmfsw)
151
{
152
    int f;
153
    int i, j;
154
155
    for (i = 0; i < MAX_FILTER_PLIES; ++i)
156
        for (j = 0; j <= i; ++j) {
157
158
            f = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pmfsw->aapwEnable[i][j]));
159
160
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwA[i][j]), f);
161
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwET[i][j]), f);
162
            gtk_widget_set_sensitive(GTK_WIDGET(pmfsw->aapwT[i][j]), f);
163
        }
164
165
    AcceptChanged(pw, pmfsw);
166
}
167
168
169
170
171
static void
172
SetupSettingsMenuActivate(GtkWidget * combo, const movefiltersetupwidget * pfmsw)
173
{
174
175
    int iSelected = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
176
177
    if (iSelected == NUM_MOVEFILTER_SETTINGS)
178
        return;                 /* user defined */
179
180
    MoveFilterSetupSetValues(aaamfMoveFilterSettings[iSelected], pfmsw);
181
182
}
183
184
185
186
187
static GtkWidget *
188
MoveFilterPage(const int i, const int j,
189
               movefilter UNUSED(aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES]), movefiltersetupwidget * pmfsw)
190
{
191
192
    GtkWidget *pwPage;
193
    GtkWidget *pwhbox;
194
    GtkWidget *pw;
195
196
    pwPage = gtk_vbox_new(FALSE, 0);
197
198
    /* enable */
199
200
    pmfsw->aapwEnable[i][j] = gtk_check_button_new_with_label(_("Enable this level"));
201
    gtk_box_pack_start(GTK_BOX(pwPage), pmfsw->aapwEnable[i][j], FALSE, FALSE, 0);
202
203
    g_signal_connect(G_OBJECT(pmfsw->aapwEnable[i][j]), "toggled", G_CALLBACK(EnableToggled), pmfsw);
204
205
    /* accept */
206
207
    pwhbox = gtk_hbox_new(FALSE, 0);
208
    pmfsw->aapwA[i][j] = pwhbox;
209
    gtk_box_pack_start(GTK_BOX(pwPage), pwhbox, FALSE, FALSE, 0);
210
211
    gtk_box_pack_start(GTK_BOX(pwhbox), gtk_label_new(_("Always accept: ")), FALSE, FALSE, 0);
212
    pmfsw->aapadjAccept[i][j] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 1000, 1, 5, 0));
213
214
    pw = gtk_spin_button_new(GTK_ADJUSTMENT(pmfsw->aapadjAccept[i][j]), 1, 0);
215
216
    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(pw), TRUE);
217
218
    gtk_box_pack_start(GTK_BOX(pwhbox), pw, FALSE, FALSE, 0);
219
220
    gtk_box_pack_start(GTK_BOX(pwhbox), gtk_label_new(_("moves.")), FALSE, FALSE, 0);
221
222
    g_signal_connect(G_OBJECT(pmfsw->aapadjAccept[i][j]), "value-changed", G_CALLBACK(AcceptChanged), pmfsw);
223
224
    /* extra */
225
226
    pwhbox = gtk_hbox_new(FALSE, 0);
227
    pmfsw->aapwET[i][j] = pwhbox;
228
    gtk_box_pack_start(GTK_BOX(pwPage), pwhbox, FALSE, FALSE, 0);
229
230
    gtk_box_pack_start(GTK_BOX(pwhbox), gtk_label_new(_("Add extra: ")), FALSE, FALSE, 0);
231
232
    pmfsw->aapadjExtra[i][j] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 1000, 1, 5, 0));
233
234
    pw = gtk_spin_button_new(GTK_ADJUSTMENT(pmfsw->aapadjExtra[i][j]), 1, 0);
235
236
    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(pw), TRUE);
237
238
    gtk_box_pack_start(GTK_BOX(pwhbox), pw, FALSE, FALSE, 0);
239
240
    g_signal_connect(G_OBJECT(pmfsw->aapadjExtra[i][j]), "value-changed", G_CALLBACK(AcceptChanged), pmfsw);
241
242
    /* threshold */
243
244
    gtk_box_pack_start(GTK_BOX(pwhbox), gtk_label_new(_("moves within")), FALSE, FALSE, 0);
245
246
    pmfsw->aapadjThreshold[i][j] = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 10, 0.001, 0.1, 0));
247
248
    pw = gtk_spin_button_new(GTK_ADJUSTMENT(pmfsw->aapadjThreshold[i][j]), 1, 3);
249
    pmfsw->aapwT[i][j] = pw;
250
251
    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(pw), TRUE);
252
253
    gtk_box_pack_start(GTK_BOX(pwhbox), pw, TRUE, TRUE, 0);
254
255
    g_signal_connect(G_OBJECT(pmfsw->aapadjThreshold[i][j]), "value-changed", G_CALLBACK(AcceptChanged), pmfsw);
256
257
258
259
    return pwPage;
260
261
}
262
263
264
265
266
static GtkWidget *
267
MoveFilterSetup(movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES], int *pfOK)
268
{
269
270
    GtkWidget *pwSetup;
271
    GtkWidget *pwFrame;
272
    int i, j;
273
    movefiltersetupwidget *pmfsw;
274
    GtkWidget *pwNotebook;
275
    GtkWidget *pwvbox;
276
277
    pwSetup = gtk_vbox_new(FALSE, 4);
278
279
    pmfsw = (movefiltersetupwidget *) g_malloc(sizeof(movefiltersetupwidget));
280
281
    /* predefined settings */
282
283
    /* output widget (with "User defined", or "Large" etc */
284
285
    pwFrame = gtk_frame_new(_("Predefined move filters:"));
286
    gtk_box_pack_start(GTK_BOX(pwSetup), pwFrame, TRUE, TRUE, 0);
287
    pmfsw->pwOptionMenu = gtk_combo_box_text_new();
288
    for (i = 0; i <= NUM_MOVEFILTER_SETTINGS; i++) {
289
290
        if (i < NUM_MOVEFILTER_SETTINGS)
291
            gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pmfsw->pwOptionMenu), Q_(aszMoveFilterSettings[i]));
292
        else
293
            gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pmfsw->pwOptionMenu), _("user defined"));
294
    }
295
296
    g_signal_connect(G_OBJECT(pmfsw->pwOptionMenu), "changed", G_CALLBACK(SetupSettingsMenuActivate), pmfsw);
297
298
    gtk_container_add(GTK_CONTAINER(pwFrame), pmfsw->pwOptionMenu);
299
300
    /* notebook with pages for each ply */
301
302
    pwNotebook = gtk_notebook_new();
303
    gtk_box_pack_start(GTK_BOX(pwSetup), pwNotebook, FALSE, FALSE, 0);
304
305
    for (i = 0; i < MAX_FILTER_PLIES; ++i) {
306
307
        char *sz = g_strdup_printf(_("%d-ply"), i + 1);
308
309
        pwvbox = gtk_vbox_new(FALSE, 4);
310
        gtk_notebook_append_page(GTK_NOTEBOOK(pwNotebook), pwvbox, gtk_label_new(sz));
311
        g_free(sz);
312
313
        for (j = 0; j <= i; ++j) {
314
315
            sz = g_strdup_printf(_("%d-ply"), j);
316
            pwFrame = gtk_frame_new(sz);
317
            g_free(sz);
318
319
            gtk_box_pack_start(GTK_BOX(pwvbox), pwFrame, FALSE, FALSE, 4);
320
321
            gtk_container_add(GTK_CONTAINER(pwFrame), MoveFilterPage(i, j, aamf, pmfsw));
322
323
        }
324
325
    }
326
327
    g_object_set_data_full(G_OBJECT(pwSetup), "user_data", pmfsw, g_free);
328
329
    pmfsw->pfOK = pfOK;
330
    pmfsw->pmf = aamf[0];
331
332
    MoveFilterSetupSetValues(aamf, pmfsw);
333
334
    return pwSetup;
335
336
}
337
338
static void
339
MoveFilterSetupOK(GtkWidget * pw, GtkWidget * pwMoveFilterSetup)
340
{
341
342
    movefiltersetupwidget *pmfsw = (movefiltersetupwidget *)
343
        g_object_get_data(G_OBJECT(pwMoveFilterSetup), "user_data");
344
345
346
    if (pmfsw->pfOK)
347
        *pmfsw->pfOK = TRUE;
348
349
    MoveFilterSetupGetValues(pmfsw->pmf, pmfsw);
350
351
    if (pmfsw->pfOK)
352
        gtk_widget_destroy(gtk_widget_get_toplevel(pw));
353
354
}
355
356
357
typedef void (*changed) (GtkWidget * pw, gpointer p);
358
359
static void
360
MoveFilterChanged(const movefilterwidget * pmfw)
361
{
362
363
    unsigned int i;
364
    int fFound = FALSE;
365
    movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
366
367
    memcpy(aamf, pmfw->pmf, sizeof(aamf));
368
369
    for (i = 0; i < NUM_MOVEFILTER_SETTINGS; ++i)
370
        if (equal_movefilters(aamf, aaamfMoveFilterSettings[i])) {
371
            gtk_combo_box_set_active(GTK_COMBO_BOX(pmfw->pwOptionMenu), i);
372
            fFound = TRUE;
373
            break;
374
        }
375
376
    if (!fFound)
377
        gtk_combo_box_set_active(GTK_COMBO_BOX(pmfw->pwOptionMenu), NUM_MOVEFILTER_SETTINGS);
378
379
    /* callback for parent */
380
381
    if (pmfw->pfChanged)
382
        ((changed) (*pmfw->pfChanged)) (NULL, pmfw->userdata);
383
384
}
385
386
387
static void
388
SettingsMenuActivate(GtkWidget * combo, movefilterwidget * pmfw)
389
{
390
391
    int iSelected = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
392
393
    if (iSelected == NUM_MOVEFILTER_SETTINGS)
394
        return;                 /* user defined */
395
396
    memcpy(pmfw->pmf, aaamfMoveFilterSettings[iSelected], MAX_FILTER_PLIES * MAX_FILTER_PLIES * sizeof(movefilter));
397
398
    MoveFilterChanged(pmfw);
399
400
}
401
402
403
static void
404
ModifyClickButton(GtkWidget * pw, movefilterwidget * pmfw)
405
{
406
407
    int fOK;
408
    GtkWidget *pwDialog;
409
    GtkWidget *pwMoveFilterSetup;
410
    movefilter aamf[MAX_FILTER_PLIES][MAX_FILTER_PLIES];
411
412
    memcpy(aamf, pmfw->pmf, sizeof(aamf));
413
    pwMoveFilterSetup = MoveFilterSetup(aamf, &fOK);
414
415
    pwDialog = GTKCreateDialog(_("GNU Backgammon - Move filter setup"),
416
                               DT_QUESTION, pw, DIALOG_FLAG_MODAL, G_CALLBACK(MoveFilterSetupOK), pwMoveFilterSetup);
417
418
    gtk_container_add(GTK_CONTAINER(DialogArea(pwDialog, DA_MAIN)), pwMoveFilterSetup);
419
420
    GTKRunDialog(pwDialog);
421
422
    if (fOK) {
423
        memcpy(pmfw->pmf, aamf, sizeof(aamf));
424
        MoveFilterChanged(pmfw);
425
    }
426
427
}
428
429
430
extern GtkWidget *
431
MoveFilterWidget(movefilter * pmf, int *UNUSED(pfOK), GCallback pfChanged, gpointer userdata)
432
{
433
434
    GtkWidget *pwFrame;
435
    movefilterwidget *pmfw;
436
    GtkWidget *pw;
437
    GtkWidget *pwButton;
438
    int i;
439
440
    pwFrame = gtk_frame_new(_("Move filter"));
441
    pmfw = (movefilterwidget *) g_malloc(sizeof(movefilterwidget));
442
    pmfw->pmf = pmf;
443
    pmfw->userdata = userdata;
444
    pmfw->pfChanged = NULL;     /* UGLY; see comment later */
445
446
    /* output widget (with "User defined", or "Large" etc */
447
448
    pw = gtk_hbox_new(FALSE, 4);
449
    gtk_container_add(GTK_CONTAINER(pwFrame), pw);
450
    pmfw->pwOptionMenu = gtk_combo_box_text_new();
451
    for (i = 0; i <= NUM_MOVEFILTER_SETTINGS; i++) {
452
453
        if (i < NUM_MOVEFILTER_SETTINGS)
454
            gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pmfw->pwOptionMenu), Q_(aszMoveFilterSettings[i]));
455
        else
456
            gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(pmfw->pwOptionMenu), _("user defined"));
457
458
    }
459
    g_signal_connect(G_OBJECT(pmfw->pwOptionMenu), "changed", G_CALLBACK(SettingsMenuActivate), pmfw);
460
461
    gtk_box_pack_start(GTK_BOX(pw), pmfw->pwOptionMenu, TRUE, TRUE, 0);
462
463
    /* Button */
464
465
    pwButton = gtk_button_new_with_label(_("Modify..."));
466
    gtk_box_pack_end(GTK_BOX(pw), pwButton, FALSE, FALSE, 0);
467
468
    g_signal_connect(G_OBJECT(pwButton), "clicked", G_CALLBACK(ModifyClickButton), pmfw);
469
470
    /* save movefilterwidget */
471
472
    g_object_set_data_full(G_OBJECT(pwFrame), "user_data", pmfw, g_free);
473
474
    MoveFilterChanged(pmfw);
475
476
    /* don't set pfChanged until here, as we don't want to call EvalChanged
477
     * just yet. This is a big ugly... */
478
    pmfw->pfChanged = pfChanged;
479
480
    return pwFrame;
481
482
}
483
484
extern void
485
SetMovefilterCommands(const char *sz,
486
                      movefilter aamfNew[MAX_FILTER_PLIES][MAX_FILTER_PLIES],
487
                      movefilter aamfOld[MAX_FILTER_PLIES][MAX_FILTER_PLIES])
488
{
489
490
    int i, j;
491
    char *szCmd;
492
    gchar buf[G_ASCII_DTOSTR_BUF_SIZE];
493
494
    for (i = 0; i < MAX_FILTER_PLIES; ++i)
495
        for (j = 0; j <= i; ++j) {
496
            if (memcmp(&aamfNew[i][j], &aamfOld[i][j], sizeof(movefilter)) != 0) {
497
                szCmd = g_strdup_printf("%s %d %d %d %d %s",
498
                                        sz, i + 1, j,
499
                                        aamfNew[i][j].Accept,
500
                                        aamfNew[i][j].Extra,
501
                                        g_ascii_formatd(buf, G_ASCII_DTOSTR_BUF_SIZE, "%0.3f",
502
                                                        (double) aamfNew[i][j].Threshold));
503
                UserCommand(szCmd);
504
                g_free(szCmd);
505
            }
506
507
        }
508
    UserCommand("save settings");
509
510
}
511
512
extern void
513
MoveFilterSetPredefined(GtkWidget * pwMoveFilter, const int i)
514
{
515
516
517
    movefilterwidget *pmfw = (movefilterwidget *)
518
        g_object_get_data(G_OBJECT(pwMoveFilter), "user_data");
519
520
    if (i < 0)
521
        return;
522
523
    memcpy(pmfw->pmf, aaamfMoveFilterSettings[i], MAX_FILTER_PLIES * MAX_FILTER_PLIES * sizeof(movefilter));
524
525
    gtk_combo_box_set_active(GTK_COMBO_BOX(pmfw->pwOptionMenu), i);
526
527
    MoveFilterChanged(pmfw);
1933 by thyssen
Use Michael Depreli's set of predefined filters, and introduce 0 as an
528
529
}