1
/* This file is a part of gtkboard, a board games system.
2
Copyright (C) 2003, Arthur J. O'Dwyer <ajo@andrew.cmu.edu>
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
24
#include "../pixmaps/alpha.xpm"
25
#include "../pixmaps/cpento.xpm"
27
#define CPENTO_CELL_SIZE 36
28
#define CPENTO_BOARD_WID 15
29
#define CPENTO_BOARD_HEIT 9
31
#define CPENTO_NUM_PIECES 32
32
#define CPENTO_EMPTY 0
33
#define CPENTO_TILE_F 1
34
#define CPENTO_TILE_I 2
35
#define CPENTO_TILE_L 3
36
#define CPENTO_TILE_N 4
37
#define CPENTO_TILE_P 5
38
#define CPENTO_TILE_T 6
39
#define CPENTO_TILE_U 7
40
#define CPENTO_TILE_V 8
41
#define CPENTO_TILE_W 9
42
#define CPENTO_TILE_X 10
43
#define CPENTO_TILE_Y 11
44
#define CPENTO_TILE_Z 12
45
#define CPENTO_TILE_SIMPLE 13
46
#define CPENTO_TILE_RARROW 14
47
#define CPENTO_TILE_LARROW 15
48
#define CPENTO_TILE_FLIPLR 16
49
#define CPENTO_PIECE_BALL 17
50
#define CPENTO_PIECE_LEG_UP 18
51
#define CPENTO_PIECE_LEG_DOWN 19
52
#define CPENTO_PIECE_PIPE_VERT 20
53
#define CPENTO_PIECE_LEG_RIGHT 21
54
#define CPENTO_PIECE_BEND_UR 22
55
#define CPENTO_PIECE_BEND_DR 23
56
#define CPENTO_PIECE_T_LEFT 24
57
#define CPENTO_PIECE_LEG_LEFT 25
58
#define CPENTO_PIECE_BEND_UL 26
59
#define CPENTO_PIECE_BEND_DL 27
60
#define CPENTO_PIECE_T_RIGHT 28
61
#define CPENTO_PIECE_PIPE_HORIZ 29
62
#define CPENTO_PIECE_T_DOWN 30
63
#define CPENTO_PIECE_T_UP 31
64
#define CPENTO_PIECE_FOURWAY 32
67
static char cpento_colors[6];
68
static int cpento_initpos[CPENTO_BOARD_WID*CPENTO_BOARD_HEIT];
69
static char **cpento_pixmaps[CPENTO_NUM_PIECES];
70
static void cpento_init();
72
static int cpento_getmove(Pos *, int, int,
74
Player, byte **, int **);
78
CPENTO_BOARD_WID, CPENTO_BOARD_HEIT,
80
cpento_colors, cpento_initpos,
82
"Capture Pentominoes",
87
static char cpento_colors[6] = { 0,120,0, 10,130,10 };
90
static int cpento_initpos[CPENTO_BOARD_WID*CPENTO_BOARD_HEIT] =
92
1, 2, 3, 4, 5, 6,13,13,13,13,13,13,13,13,13,
93
7, 8, 9,10,11,12,13, 0, 0, 0, 0, 0, 0, 0,13,
94
13,13,13,13,13,13,13, 0, 0, 0, 0, 0, 0, 0,13,
95
13, 0, 0, 0, 0, 0,13, 0, 0, 0, 0, 0, 0, 0,13,
96
13, 0, 0, 0, 0, 0,13, 0, 0, 0, 0, 0, 0, 0,13,
97
15, 0, 0, 0, 0, 0,14, 0, 0, 0, 0, 0, 0, 0,13,
98
13, 0, 0, 0, 0, 0,13, 0, 0, 0, 0, 0, 0, 0,13,
99
13, 0, 0, 0, 0, 0,13, 0, 0, 0, 0, 0, 0, 0,13,
100
13,13,13,16,13,13,13,13,13,13,13,13,13,13,13,
103
static char *ball_grey_36_36_xpm[] = {
107
"....................................",
108
"....................................",
109
".................X..................",
110
"............XXXXXXXXXXX.............",
111
"..........XXXXXXXXXXXXXXX...........",
112
"........XXXXXXXXXXXXXXXXXXX.........",
113
".......XXXXXXXXXXXXXXXXXXXXX........",
114
"......XXXXXXXXXXXXXXXXXXXXXXX.......",
115
".....XXXXXXXXXXXXXXXXXXXXXXXXX......",
116
".....XXXXXXXXXXXXXXXXXXXXXXXXX......",
117
"....XXXXXXXXXXXXXXXXXXXXXXXXXXX.....",
118
"....XXXXXXXXXXXXXXXXXXXXXXXXXXX.....",
119
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
120
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
121
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
122
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
123
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
124
"..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...",
125
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
126
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
127
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
128
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
129
"...XXXXXXXXXXXXXXXXXXXXXXXXXXXXX....",
130
"....XXXXXXXXXXXXXXXXXXXXXXXXXXX.....",
131
"....XXXXXXXXXXXXXXXXXXXXXXXXXXX.....",
132
".....XXXXXXXXXXXXXXXXXXXXXXXXX......",
133
".....XXXXXXXXXXXXXXXXXXXXXXXXX......",
134
"......XXXXXXXXXXXXXXXXXXXXXXX.......",
135
".......XXXXXXXXXXXXXXXXXXXXX........",
136
"........XXXXXXXXXXXXXXXXXXX.........",
137
"..........XXXXXXXXXXXXXXX...........",
138
"............XXXXXXXXXXX.............",
139
".................X..................",
140
"....................................",
141
"....................................",
142
"....................................",
146
static char **cpento_pixmaps[CPENTO_NUM_PIECES] =
148
char_F_grey_36_36_xpm,
149
char_I_grey_36_36_xpm,
150
char_L_grey_36_36_xpm,
151
char_N_grey_36_36_xpm,
152
char_P_grey_36_36_xpm,
153
char_T_grey_36_36_xpm,
154
char_U_grey_36_36_xpm,
155
char_V_grey_36_36_xpm,
156
char_W_grey_36_36_xpm,
157
char_X_grey_36_36_xpm,
158
char_Y_grey_36_36_xpm,
159
char_Z_grey_36_36_xpm,
160
cpento_fourway_36_36_xpm,
161
char_R_grey_36_36_xpm,
162
char_L_grey_36_36_xpm,
163
char_F_grey_36_36_xpm,
165
cpento_leg_u_36_36_xpm,
166
cpento_leg_d_36_36_xpm,
167
cpento_pipe_ud_36_36_xpm,
168
cpento_leg_r_36_36_xpm,
169
cpento_bend_ur_36_36_xpm,
170
cpento_bend_dr_36_36_xpm,
171
cpento_t_closed_l_36_36_xpm,
172
cpento_leg_l_36_36_xpm,
173
cpento_bend_ul_36_36_xpm,
174
cpento_bend_dl_36_36_xpm,
175
cpento_t_closed_r_36_36_xpm,
176
cpento_pipe_lr_36_36_xpm,
177
cpento_t_closed_d_36_36_xpm,
178
cpento_t_closed_u_36_36_xpm,
179
cpento_fourway_36_36_xpm,
183
static void cpento_init()
185
game_single_player = 1;
186
game_getmove = cpento_getmove;
188
game_get_pixmap = NULL;
189
game_scorecmp = game_scorecmp_def_iscore;
190
game_doc_about_status = STATUS_UNPLAYABLE;
192
"Capture Pentominoes\n"
194
"Status: Not implemented\n"
195
"URL: " GAME_DEFAULT_URL("cpento")
198
"The objective is to be the last player able to move.\n"
200
"Each move consists of selecting a piece from the pool"
201
" and placing it on some empty region of the board."
202
" If the newly placed piece touches a second piece on"
203
" three or more sides, that second piece is captured."
204
" A captured piece may be removed from the board by"
205
" its captor at any time.\n"
207
"At the moment, this is just an interface demo. There's"
208
" no actual game implemented.\n"
216
static char *cpento_piece_list[][5] = {
304
static void cpento_add_move(byte *move, int x, int y, int m)
307
for (i=0; move[i] != -1; i += 3)
309
if (move[i] == x && move[i+1] == y) {
322
static void cpento_clear_left(byte *move)
326
/* Clear the left side of the board */
327
for (i=1; i < 6; ++i)
328
for (j=1; j < 6; ++j)
330
cpento_add_move(move, i, j, 0);
334
/* From picture coords to display coords */
335
static void cpento_orient(int x, int y, int *nx, int *ny, int orient)
339
case 0: *nx = x; *ny = y; return;
340
case 1: *nx = 4-y; *ny = x; return;
341
case 2: *nx = 4-x; *ny = 4-y; return;
342
case 3: *nx = y; *ny = 4-x; return;
343
case 4: *nx = 4-x; *ny = y; return;
344
case 5: *nx = y; *ny = x; return;
345
case 6: *nx = x; *ny = 4-y; return;
346
case 7: *nx = 4-y; *ny = 4-x; return;
350
/* From display coords to picture coords */
351
static void cpento_rev_orient(int x, int y, int *nx, int *ny, int orient)
355
case 0: *nx = x; *ny = y; return;
356
case 1: *nx = y; *ny = 4-x; return;
357
case 2: *nx = 4-x; *ny = 4-y; return;
358
case 3: *nx = 4-y; *ny = x; return;
359
case 4: *nx = 4-x; *ny = y; return;
360
case 5: *nx = y; *ny = x; return;
361
case 6: *nx = x; *ny = 4-y; return;
362
case 7: *nx = 4-y; *ny = 4-x; return;
366
static int cpento_tile_orient(int x, int y, int orient, char **pento)
369
int top=0, left=0, right=0, bottom=0;
374
CPENTO_PIECE_LEG_DOWN,
375
CPENTO_PIECE_PIPE_VERT,
376
CPENTO_PIECE_LEG_RIGHT,
377
CPENTO_PIECE_BEND_UR,
378
CPENTO_PIECE_BEND_DR,
380
CPENTO_PIECE_LEG_LEFT,
381
CPENTO_PIECE_BEND_UL,
382
CPENTO_PIECE_BEND_DL,
383
CPENTO_PIECE_T_RIGHT,
384
CPENTO_PIECE_PIPE_HORIZ,
390
cpento_rev_orient(x, y, &tx, &ty, orient);
391
if (pento[tx][ty] != 'X')
393
cpento_rev_orient(x, y+1, &tx, &ty, orient);
394
top = (y < 4 && pento[tx][ty] == 'X');
395
cpento_rev_orient(x, y-1, &tx, &ty, orient);
396
bottom = (y > 0 && pento[tx][ty] == 'X');
397
cpento_rev_orient(x+1, y, &tx, &ty, orient);
398
right = (x < 4 && pento[tx][ty] == 'X');
399
cpento_rev_orient(x-1, y, &tx, &ty, orient);
400
left = (x > 0 && pento[tx][ty] == 'X');
401
return results[top | bottom<<1 | right<<2 | left<<3];
404
static void cpento_place_left(byte *move, char *pento[5],
405
int piece_letter, int orient)
408
cpento_clear_left(move);
409
for (i=0; i < 5; ++i) {
410
for (j=0; j < 5; ++j) {
412
cpento_orient(i, j, &X, &Y, orient);
413
if (pento[i][j] == 'X')
414
cpento_add_move(move, X+1, Y+1,
415
cpento_tile_orient(X, Y, orient, pento));
421
static void cpento_place_right(byte *move, char *pento[5],
422
int piece_letter, int orient,
426
for (i=0; i < 5; ++i) {
427
for (j=0; j < 5; ++j) {
429
cpento_orient(i, j, &X, &Y, orient);
430
if (pento[i][j] == 'X')
431
cpento_add_move(move, X+x-2, Y+y-2,
432
cpento_tile_orient(X, Y, orient, pento));
438
static int cpento_fits_right(byte *move, char *pento[5],
439
int orient, int x, int y, Pos *pos)
442
for (i=0; i < 5; ++i) {
443
for (j=0; j < 5; ++j) {
445
cpento_orient(i, j, &X, &Y, orient);
446
if (pento[i][j] == 'X') {
447
if (X+x-2 < 1 || X+x-2 > CPENTO_BOARD_WID-2)
449
if (Y+y-2 < 1 || Y+y-2 > CPENTO_BOARD_HEIT-2)
451
if (pos->board[(Y+y-2)*board_wid + (X+x-2)] != CPENTO_EMPTY)
460
static int cpento_getmove(Pos *pos, int x, int y,
461
GtkboardEventType type,
462
Player to_play, byte **movp,
465
static byte move[2000]; /* theoretical max length: 151 */
466
static int state = 0;
467
static int orient = 0;
468
static int pento = 0;
472
/* 0 = no pentomino selected */
473
/* 1 = pentomino selected */
476
/* 1 = rot 90 right */
477
/* 2 = rot 180 right */
478
/* 5 = flipped, then rot 90 */
479
/* 7 = flipped, then rot 270 */
480
/* Pentos run 0..11 */
482
static const int larrow_effects[] =
483
{ 1, 2, 3, 0, 7, 4, 5, 6 };
484
static const int rarrow_effects[] =
485
{ 3, 0, 1, 2, 5, 6, 7, 4 };
486
static const int fliplr_effects[] =
487
{ 4, 5, 6, 7, 0, 1, 2, 3 };
489
if (type != GTKBOARD_BUTTON_RELEASE)
494
tile = pos->board[y * board_wid + x];
496
if (tile >= CPENTO_TILE_F && tile <= CPENTO_TILE_Z)
498
/* Select a new pentomino; get rid of the old one */
499
pento = (tile - CPENTO_TILE_F);
501
cpento_place_left(move, cpento_piece_list[pento], tile, orient);
507
else if ((tile == CPENTO_TILE_LARROW) && (state == 1))
509
orient = larrow_effects[orient];
510
cpento_place_left(move, cpento_piece_list[pento], pento, orient);
515
else if ((tile == CPENTO_TILE_RARROW) && (state == 1))
517
orient = rarrow_effects[orient];
518
cpento_place_left(move, cpento_piece_list[pento], pento, orient);
523
else if ((tile == CPENTO_TILE_FLIPLR) && (state == 1))
525
orient = fliplr_effects[orient];
526
cpento_place_left(move, cpento_piece_list[pento], pento, orient);
531
else if (tile != CPENTO_EMPTY)
535
else if ((x > 6) && (state == 1))
537
cpento_clear_left(move);
538
if (cpento_fits_right(move, cpento_piece_list[pento], orient, x, y, pos))
540
cpento_place_right(move, cpento_piece_list[pento], pento, orient, x, y);
549
if (cpento_fits_right(move, cpento_piece_list[pento], orient,
551
++possibles, fit = 0 * 3 + 1;
552
if (cpento_fits_right(move, cpento_piece_list[pento], orient,
554
++possibles, fit = 2 * 3 + 1;
555
if (cpento_fits_right(move, cpento_piece_list[pento], orient,
557
++possibles, fit = 1 * 3 + 0;
558
if (cpento_fits_right(move, cpento_piece_list[pento], orient,
560
++possibles, fit = 1 * 3 + 2;
565
cpento_place_right(move, cpento_piece_list[pento], pento, orient,
566
x+(fit/3)-1, y+(fit%3)-1);