1
/* This file is a part of gtkboard, a board games system.
2
Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
27
#include "../pixmaps/chess.xpm"
28
#include "../pixmaps/misc.xpm"
30
#define KTTOUR_CELL_SIZE 54
31
#define KTTOUR_NUM_PIECES 4
33
#define KTTOUR_BOARD_WID 8
34
#define KTTOUR_BOARD_HEIT 8
36
#define KTTOUR_EMPTY 0
38
#define KTTOUR_START 2
42
char kttour_colors[6] = {200, 200, 160, 200, 200, 160};
46
Game Kttour = { KTTOUR_CELL_SIZE, KTTOUR_BOARD_WID, KTTOUR_BOARD_HEIT,
48
kttour_colors, NULL, /*kttour_pixmaps,*/ NULL, "Knight's Tour", NULL,
51
SCORE_FIELD kttour_score_fields[] = {SCORE_FIELD_RANK, SCORE_FIELD_USER, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE};
52
char *kttour_score_field_names[] = {"Rank", "User", "Time", "Date", NULL};
54
static int kttour_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
55
static ResultType kttour_who_won (Pos *, Player, char **);
56
static char **kttour_get_pixmap (int , int);
60
game_single_player = 1;
61
game_getmove = kttour_getmove;
62
game_get_pixmap = kttour_get_pixmap;
63
game_who_won = kttour_who_won;
64
game_scorecmp = game_scorecmp_def_time;
65
game_score_fields = kttour_score_fields;
66
game_score_field_names = kttour_score_field_names;
67
game_draw_cell_boundaries = TRUE;
68
game_allow_undo = TRUE;
69
game_doc_about_status = STATUS_COMPLETE;
72
"Single player game\n"
73
"Status: Partially implemented\n"
74
"URL: "GAME_DEFAULT_URL("kttour");
76
" Complete the knight's tour of the chessboard.\n"
78
" In the initial position click on any square to start the tour on that square. "
79
"Next click on the square you want the knight to move to, and so on. "
80
"The square where you started will be shown in green and the other squares in the tour will be grey. "
81
"At any point you can click on the green square to make it the current square, in which case the current square will become the \"start\" square. "
83
" The objective is to fill all 64 squares in such a way that the last square is one knight-move away from the first, in as little time as possible. "
84
"In this game, you can undo your moves freely. This won't prevent you from getting a highscore. "
86
" The blue balls that you see are hints. They are there to make your life easier, but you don't have to necessarily click on a ball."
90
static char **kttour_get_pixmap (int idx, int color)
92
static char pixbuf[KTTOUR_CELL_SIZE*(KTTOUR_CELL_SIZE+1)];
94
for(i=0, bg=0;i<3;i++)
95
{ int col = kttour_colors[i]; if (col<0) col+=256; bg += col * (1 << (16-8*i));}
99
return chess_wn_54_xpm;
101
// simulate square using ball of large radius
103
return pixmap_ball_gen (KTTOUR_CELL_SIZE, pixbuf, 0x80ff80, bg,
104
KTTOUR_CELL_SIZE, 1);
106
return pixmap_ball_gen (KTTOUR_CELL_SIZE, pixbuf, 0x808080, bg,
107
KTTOUR_CELL_SIZE, 1);
110
return pixmap_ball_gen (KTTOUR_CELL_SIZE, pixbuf, 0x8080ff, bg,
111
KTTOUR_CELL_SIZE/4, 30.0);
112
default: return NULL;
116
#define abs(x) ((x)<0?-(x):(x))
118
static gboolean are_nbrs (int x1, int y1, int x2, int y2)
120
return abs ((x1 - x2) * (y1 - y2)) == 2 ? TRUE : FALSE;
123
/* TODO: this should be implemented in game_common.c or something like that so that
124
all games can access it */
125
static void find_xy (byte *board, int *x, int *y, int val)
130
for (i=0; i<board_wid; i++)
131
for (j=0; j<board_wid; j++)
132
if (board[j * board_wid + i] == val)
140
ResultType kttour_who_won (Pos *pos, Player to_play, char **commp)
144
gboolean found = FALSE;
145
for (i=0; i<board_wid*board_heit; i++)
146
if (pos->board [i] == KTTOUR_EMPTY)
147
return RESULT_NOTYET;
148
find_xy (pos->board, &x1, &y1, KTTOUR_CUR);
149
find_xy (pos->board, &x2, &y2, KTTOUR_START);
150
return are_nbrs (x1, y1, x2, y2) ? RESULT_WON : RESULT_NOTYET;
153
static int incx[] = {-2, -2, -1, -1, 1, 1, 2, 2};
154
static int incy[] = {-1, 1, -2, 2, -2, 2, -1, 1};
156
#define IS_FREE(x) ((x) == KTTOUR_EMPTY || (x) == KTTOUR_HINT)
158
static int get_degree (byte *board, int i, int j)
166
if (ISINBOARD (x, y) && IS_FREE(board [y * board_wid + x]))
172
static int get_min_degree (byte *board, int i, int j)
181
if (ISINBOARD (x, y) && IS_FREE(board [y * board_wid + x]))
182
if ((deg = get_degree (board, x, y)) < min_deg)
188
static void add_hints
189
(byte *board, int new_x, int new_y, byte **mp)
191
int min_deg_new, min_deg_old;
193
min_deg_new = get_min_degree (board, new_x, new_y);
199
if (!ISINBOARD (x, y) || board [y * board_wid + x] != KTTOUR_EMPTY)
201
if (get_degree (board, x, y) == min_deg_new)
205
*(*mp)++ = KTTOUR_HINT;
209
for (x=0; x<board_wid; x++)
210
for (y=0; y<board_heit; y++)
212
if (board [y * board_wid + x] != KTTOUR_HINT)
214
if (x == new_x && y == new_y)
216
if (are_nbrs (x, y, new_x, new_y) && get_degree (board, x, y) == min_deg_new)
220
*(*mp)++ = KTTOUR_EMPTY;
225
(Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
231
if (type != GTKBOARD_BUTTON_RELEASE)
233
val = pos->board[y * board_wid + x];
234
if (val == KTTOUR_CUR)
236
if (val == KTTOUR_USED)
238
find_xy (pos->board, &cur_x, &cur_y, KTTOUR_CUR);
239
if (val == KTTOUR_START)
246
*mp++ = KTTOUR_START;
247
add_hints (pos->board, x, y, &mp);
252
if (cur_x >= 0 && !are_nbrs (cur_x, cur_y, x, y))
261
*mp++ = pos->num_moves == 1 ? KTTOUR_START : KTTOUR_USED;
263
add_hints (pos->board, x, y, &mp);