This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

quarto.c

Go to the documentation of this file.
00001 /*  This file is a part of gtkboard, a board games system.
00002     Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
00017 
00018 */
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <assert.h>
00022 #include <stdlib.h>
00023 
00024 #include "game.h"
00025 #include "aaball.h"
00026 
00027 #define QUARTO_CELL_SIZE 60
00028 #define QUARTO_NUM_PIECES 17
00029 
00030 #define QUARTO_BOARD_WID 9
00031 #define QUARTO_BOARD_HEIT 4
00032 
00033 #define QUARTO_EMPTY 0
00034 #define QUARTO_SEPARATOR 17
00035 
00036 #define QUARTO_SHAPE_MASK (1 << 0)
00037 #define QUARTO_SIZE_MASK  (1 << 1)
00038 #define QUARTO_HOLE_MASK  (1 << 2)
00039 #define QUARTO_COLOR_MASK (1 << 3)
00040 #define QUARTO_ALL_PIECES_MASK (QUARTO_SHAPE_MASK | QUARTO_SIZE_MASK | QUARTO_HOLE_MASK | QUARTO_COLOR_MASK)
00041 
00042 char quarto_colors[9] = {200, 200, 200, 200, 200, 200, 0, 0, 0};
00043 
00044 char quarto_highlight_colors[9] = {0, 0xff, 0, 0, 0, 0, 0, 0, 0};
00045 
00046 int quarto_init_pos[QUARTO_BOARD_HEIT * QUARTO_BOARD_WID] = 
00047 {
00048         0, 0, 0, 0, 17, 1,   2,  3,  4,
00049         0, 0, 0, 0, 17, 5,   6,  7,  8,
00050         0, 0, 0, 0, 17, 9,  10, 11, 12,
00051         0, 0, 0, 0, 17, 13, 14, 15, 16,
00052 };
00053 
00054 
00055 
00056 void quarto_init ();
00057 
00058 Game Quarto = { QUARTO_CELL_SIZE, QUARTO_BOARD_WID, QUARTO_BOARD_HEIT, 
00059         QUARTO_NUM_PIECES,
00060         quarto_colors, quarto_init_pos, NULL, "Quarto", quarto_init};
00061 
00062 
00063 static int quarto_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
00064 static ResultType quarto_who_won (Pos *, Player, char **);
00065 void quarto_init (void);
00066 static byte * quarto_movegen (Pos *);
00067 static ResultType quarto_eval (Pos *, Player, float *eval);
00068 static void quarto_reset_uistate (Pos *pos);
00069 static unsigned char * quarto_get_rgbmap (int idx, int color);
00070 void quarto_get_render (Pos *pos, byte *move, int **rmovp);
00071 
00072 void quarto_init ()
00073 {
00074         game_eval = quarto_eval;
00075         game_movegen = quarto_movegen;
00076         game_who_won = quarto_who_won;
00077         game_getmove = quarto_getmove;
00078         game_get_rgbmap = quarto_get_rgbmap;
00079         game_draw_cell_boundaries = TRUE;
00080         game_highlight_colors = quarto_highlight_colors;
00081         game_reset_uistate = quarto_reset_uistate;
00082         game_get_render = quarto_get_render;
00083         game_allow_flip = TRUE;
00084         game_doc_about = 
00085                 "Quarto\n"
00086                 "Two player game\n"
00087                 "Status: Partially implemented\n"
00088                 "URL: "GAME_DEFAULT_URL ("quarto");
00089         game_doc_rules = 
00090                 "Quarto rules\n"
00091                 "\n"
00092                 "Two players take turns in placing the pieces from the right side of the board to the left side. Get 4 in a line (horizontal, vertical, diagonal) of any one type -- big, small, square, circle, hole, no hole, red or blue";
00093 }
00094 
00095 static ResultType quarto_who_won (Pos *pos, Player player, char **commp)
00096 {
00097         ResultType result;
00098         float eval;
00099         result = quarto_eval (pos, player, &eval);
00100         if (result == RESULT_WHITE) *commp = "White won";
00101         if (result == RESULT_BLACK) *commp = "Black won";
00102         return result;
00103 }
00104 
00105 static gboolean eval_column (byte *board, int x, int y, int incx, int incy)
00106 {
00107         int i;
00108         int and1, and2;
00109         and1 = and2 = QUARTO_ALL_PIECES_MASK;
00110         for (i=0; i<4; i++, x+=incx, y+=incy)
00111         {
00112                 int val;
00113                 val = board[y * board_wid + x];
00114                 if (val == 0)
00115                         return FALSE;
00116                 val--;
00117                 and1 &= val;
00118                 and2 &= ~val;
00119         }
00120         if (and1 != 0 || and2 != 0)
00121                 return TRUE;
00122         else
00123                 return FALSE;
00124 }
00125 
00126 static ResultType quarto_eval (Pos *pos, Player player, float *eval)
00127 {
00128         int i, j;
00129         int and1, and2;
00130         ResultType result = player == WHITE ? RESULT_BLACK : RESULT_WHITE;
00131         *eval = player == WHITE ? -1 : 1;
00132 
00133         for (i=0; i<4; i++)
00134                 if (eval_column (pos->board, i, 0, 0, 1))
00135                         return result;
00136 
00137         for (j=0; j<4; j++)
00138                 if (eval_column (pos->board, 0, j, 1, 0))
00139                         return result;
00140 
00141         if (eval_column (pos->board, 0, 0, 1, 1))
00142                 return result;
00143 
00144         if (eval_column (pos->board, 0, 3, 1, -1))
00145                 return result;
00146 
00147         *eval = random() * 0.01 / RAND_MAX;
00148         return RESULT_NOTYET;
00149 }
00150 
00151 static int cur_piece = -1, curx = -1, cury = -1;
00152 
00153 int quarto_getmove 
00154         (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
00155 {
00156         static byte move[7];
00157         static int rmove[7];
00158         byte *mp = move;
00159         int *rp = rmove;
00160 
00161         if (type != GTKBOARD_BUTTON_RELEASE)
00162                 return 0;
00163         
00164         if (x == 4) return 0;
00165         
00166         if (x > 4)
00167         {
00168                 if (pos->render[y * board_wid + x] == RENDER_SHADE1)
00169                         return -1;
00170                 *rp++ = x;
00171                 *rp++ = y;
00172                 *rp++ = RENDER_HIGHLIGHT1;
00173                 if (cur_piece >= 0)
00174                 {
00175                         *rp++ = curx;
00176                         *rp++ = cury;
00177                         *rp++ = RENDER_NONE;
00178                 }
00179                 *rp++ = -1;
00180                 cur_piece = pos->board [y * board_wid + x];
00181                 curx = x;
00182                 cury = y;
00183                 *rmovep = rmove;
00184                 return 0;
00185         }
00186 
00187         if (cur_piece < 0)
00188                 return -1;
00189 
00190         if (pos->board[y * board_wid + x] != QUARTO_EMPTY)
00191                 return -1;
00192         *mp++ = x;
00193         *mp++ = y;
00194         *mp++ = cur_piece;
00195         *mp++ = -1;
00196         *movp = move;
00197         cur_piece = -1;
00198         *rp++ = curx;
00199         *rp++ = cury;
00200         *rp++ = 0;
00201         *rp++ = -1;
00202         *rmovep = rmove;
00203         return 1;
00204 }
00205 
00206 void quarto_get_render (Pos *pos, byte *move, int **rmovp)
00207 {
00208         static int rmove[4];
00209         int *rp = rmove;
00210         int val, shadeval;
00211         int i, j;
00212         if (move[2] == QUARTO_EMPTY)
00213         {
00214                 val = pos->board [move[1] * board_wid + move[0]];
00215                 shadeval = RENDER_NONE;
00216         }
00217         else
00218         { 
00219                 val = move[2];
00220                 shadeval = RENDER_SHADE1;
00221         }
00222         for (i=5; i<9; i++)
00223         for (j=0; j<4; j++)
00224                 if (pos->board[j * board_wid + i] == val)
00225                 {
00226                         *rp++ = i;
00227                         *rp++ = j;
00228                         *rp++ = shadeval;
00229                         *rp++ = -1;
00230                 }
00231         *rmovp = rmove;
00232 }
00233 
00234 void quarto_reset_uistate (Pos *pos)
00235 {
00236         cur_piece = curx = cury = -1;
00237 }
00238 
00239 byte *quarto_movegen (Pos *pos)
00240 {
00241         byte movbuf[2048];
00242         byte *movlist, *movp = movbuf;
00243         int from_x, from_y, to_x, to_y;
00244         Player player = pos->player;
00245 
00246         int count = 0;
00247         for (to_x=0; to_x<4; to_x++)
00248         for (to_y=0; to_y<4; to_y++)
00249                 if (pos->board [to_y * board_wid + to_x] != QUARTO_EMPTY)
00250                         count++;
00251         assert ((player == WHITE && count % 2 == 0) || (player == BLACK && count % 2 == 1));
00252 
00253                 
00254         for (from_x=5; from_x<9; from_x++)
00255         for (from_y=0; from_y<4; from_y++)
00256         {
00257                 gboolean found = FALSE;
00258                 int val = pos->board [from_y * board_wid + from_x];
00259                 for (to_x=0; to_x<4; to_x++)
00260                 for (to_y=0; to_y<4; to_y++)
00261                         if (val == pos->board [to_y * board_wid + to_x])
00262                         {
00263                                 found = TRUE;
00264                                 break;
00265                         }
00266                 if (!found)
00267                 {
00268                         for (to_x=0; to_x<4; to_x++)
00269                         for (to_y=0; to_y<4; to_y++)
00270                         {
00271                                 if (pos->board [to_y * board_wid + to_x] == QUARTO_EMPTY)
00272                                 {
00273                                         *movp++ = to_x;
00274                                         *movp++ = to_y;
00275                                         *movp++ = val;
00276                                         *movp++ = -1;
00277                                 }
00278                         }
00279                 }
00280         }
00281         *movp++ = -2;
00282         movlist = (byte *) (malloc (movp - movbuf));
00283         memcpy (movlist, movbuf, (movp - movbuf));
00284         return movlist;
00285 }
00286 
00287 unsigned char * quarto_get_rgbmap (int idx, int color)
00288 {
00289         int fg = 0, bg, i;
00290         char *colors;
00291         static char rgbbuf[3*QUARTO_CELL_SIZE*QUARTO_CELL_SIZE];
00292         int color1 = 0xff << 16, color2 = 0xff, sepcolor = 0xaaaa66;
00293         float grad = 30.0;
00294         int size;
00295         colors = quarto_colors;
00296         for(i=0, bg=0;i<3;i++) 
00297         { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
00298         if (idx == QUARTO_SEPARATOR)
00299         {
00300                 rgbmap_square_gen (QUARTO_CELL_SIZE, rgbbuf, sepcolor, bg, QUARTO_CELL_SIZE);
00301                 return rgbbuf;
00302         }
00303         fg = ((idx - 1) & QUARTO_COLOR_MASK) ? color1 : color2;
00304         size = ((idx - 1) & QUARTO_SIZE_MASK) ? 
00305                 3.0 * QUARTO_CELL_SIZE / 4 : QUARTO_CELL_SIZE / 2.0;
00306         if ((idx - 1) & QUARTO_SHAPE_MASK)
00307                 rgbmap_ball_gen(QUARTO_CELL_SIZE, rgbbuf, fg, bg, size/2, grad);
00308         else
00309                 rgbmap_square_gen (QUARTO_CELL_SIZE, rgbbuf, fg, bg, size);
00310         if ((idx - 1) & QUARTO_HOLE_MASK)
00311                 rgbmap_ball_gen_nobg (QUARTO_CELL_SIZE, rgbbuf, bg, fg, QUARTO_CELL_SIZE/8.0, grad);
00312         return rgbbuf;
00313         
00314 }
00315 
00316