This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

plot4.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 
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <assert.h>
00025 #include <stdlib.h>
00026 
00027 #include "game.h"
00028 #include "aaball.h"
00029 
00030 #define PLOT4_CELL_SIZE 55
00031 #define PLOT4_NUM_PIECES 3
00032 
00033 #define PLOT4_BOARD_WID 7
00034 #define PLOT4_BOARD_HEIT 6
00035 
00036 char plot4_colors[6] = {160, 140, 100, 160, 140, 100};
00037 
00038 int * plot4_init_pos = NULL;
00039 
00040 #define PLOT4_WP 1
00041 #define PLOT4_BP 2
00042 #define PLOT4_EMPTY 3
00043 
00044 
00045 void plot4_init ();
00046 
00047 Game Plot4 = { PLOT4_CELL_SIZE, PLOT4_BOARD_WID, PLOT4_BOARD_HEIT, 
00048         PLOT4_NUM_PIECES,
00049         plot4_colors,  NULL, NULL, "Plot4", plot4_init};
00050 
00051 
00052 
00053 static int eval_runs (Pos *, int);
00054 static int find_runs (byte *, int, int, int , int, int, int);
00055 static int plot4_getmove (Pos *, int, int, GtkboardEventType, Player, byte **, int **);
00056 static ResultType plot4_who_won (Pos *, Player , char **);
00057 static void plot4_set_init_pos (Pos *pos);
00058 static char ** plot4_get_pixmap (int, int);
00059 static byte * plot4_movegen (Pos *);
00060 static ResultType plot4_eval (Pos *, Player, float *);
00061 
00062 
00063 static const int RUN_WT = 20;
00064 
00065 
00066 void plot4_init ()
00067 {
00068         game_eval = plot4_eval;
00069         game_movegen = plot4_movegen;
00070         game_getmove = plot4_getmove;
00071         game_who_won = plot4_who_won;
00072         game_set_init_pos = plot4_set_init_pos;
00073         game_get_pixmap = plot4_get_pixmap;
00074         game_white_string = "Green";
00075         game_black_string = "Yellow";
00076         game_doc_about = 
00077                 "Plot4\n"
00078                 "Two player game\n"
00079                 "Status: Fully implemented\n"
00080                 "URL: "GAME_DEFAULT_URL ("plot4");
00081         game_doc_rules = 
00082                 "Plot4 rules\n"
00083                 "\n"
00084                 "Two players alternate in placing balls of either color on a 7x6 board. Not exactly placing, because the balls have gravity and fall down to the lowest unoccupied square on the column. The goal is to get as many 4-in-a-row's as possible. A 5-in-a-row counts as two, 6 as 3, and 7 as 4.\n";
00085 }
00086 
00087 void plot4_set_init_pos (Pos *pos)
00088 {
00089         int i;
00090         for (i=0; i<board_wid * board_heit; i++)
00091                 pos->board [i] = PLOT4_EMPTY;
00092 }
00093 
00094 ResultType plot4_who_won (Pos *pos, Player to_play, char **commp)
00095 {
00096         static char comment[32];
00097         char *who_str [3] = { "Green won", "Yellow won", "Its a tie" };
00098         int i, wscore, bscore, who_idx;
00099         wscore = eval_runs (pos, WHITE) / RUN_WT;
00100         bscore = eval_runs (pos, BLACK) / RUN_WT * -1;
00101         *commp = comment;
00102         for (i=0; i<board_wid * board_heit; i++)
00103                 if (pos->board[i] == PLOT4_EMPTY) 
00104                 {
00105                         snprintf (comment, 32, "%d : %d", wscore, bscore);
00106                         return RESULT_NOTYET;
00107                 }
00108         if (wscore > bscore) who_idx = 0;
00109         else if (wscore < bscore) who_idx = 1;
00110         else who_idx = 2;
00111         snprintf (comment, 32, "%s (%d : %d)", who_str[who_idx], wscore, bscore);
00112         if (wscore > bscore)
00113                 return RESULT_WHITE;
00114         if (wscore < bscore)
00115                 return RESULT_BLACK;
00116         return RESULT_TIE;
00117 }
00118 
00119 int plot4_islegal (byte *board, int x, int y)
00120         /* check bounds
00121            check if (x,y) is empty
00122            check if (x, y-1) is not empty */
00123 {
00124         return (x >= 0 && x < board_wid && y >= 0 && y < board_heit
00125                         && (board[y * board_wid + x] == PLOT4_EMPTY) && 
00126                         ((y == 0) || (board [(y-1) * board_wid + x] != PLOT4_EMPTY)));
00127 }
00128 
00129 int plot4_getmove (Pos *pos, int x, int y, GtkboardEventType type, Player to_play, byte **movp, int ** rmovep)
00130         /* translate a sequence of mouse clicks into a cbgf move.
00131            pos is the current position, x and y are the square which was
00132            clicked, type is the event type: MOUSE_PRESSED, MOUSE_RELEASED
00133            to_play is who has the move, movp is used to return the move
00134 
00135            the return value is 1 if the clicks were successfully translated
00136            into a move; -1 if the move is illegal, and 0 if further clicks
00137            are required to determine the move. In the latter case, this 
00138            function is responsible for keeping track of the current state.
00139          */
00140 {
00141         static byte move[4];
00142         if (type != GTKBOARD_BUTTON_RELEASE)
00143                 return 0;
00144         /* OK to click anywhere in the column */
00145         for (y = 0; y < board_heit; y++)
00146                 if (pos->board[y * board_wid + x] == PLOT4_EMPTY)
00147                         break;
00148         if (y == board_heit)
00149                 return -1;
00150         move[0] = x;
00151         move[1] = y;
00152         move[2] = to_play == WHITE ? PLOT4_WP : PLOT4_BP;
00153         move[3] = -1;
00154         if (movp)
00155                 *movp = move;   
00156         return 1;
00157 }
00158 
00159 ResultType plot4_eval (Pos *pos, Player to_play, float *eval)
00160         /* always eval from POV of white */
00161 {
00162         /* TODO : add some weights */
00163         *eval = eval_runs (pos, -1);
00164         return RESULT_NOTYET;
00165 }
00166 
00167 
00168 
00169 static int eval_runs (Pos *pos, int forwhom)
00170         /* sum of all the runs of forwhom (both if -1) from POV of WHITE */
00171 {
00172         int sum = 0;
00173         int i, board_min, min;
00174         byte *board = pos->board;
00175         board_min = board_wid < board_heit ? board_wid : board_heit;
00176         for (i=0; i<board_wid; i++)
00177                 sum += find_runs (board, i, 0, 0, 1, board_heit, forwhom);
00178         for (i=0; i<board_heit; i++)
00179                 sum += find_runs (board, 0, i, 1, 0, board_wid, forwhom);
00180         for (i=0; i<board_wid; i++)
00181         {
00182                 min = (board_wid - i) < board_min ? (board_wid - i) : board_min;
00183                 sum += find_runs (board, i, 0, 1, 1, min, forwhom);
00184                 sum += find_runs (board, board_wid - i - 1, 0, -1, 1, min, forwhom);
00185         }
00186         for (i=1; i<board_heit; i++)
00187         {
00188                 min = (board_heit - i) < board_min ? (board_heit - i) : board_min;
00189                 sum += find_runs (board, 0, i, 1, 1, min, forwhom);
00190                 sum += find_runs (board, board_wid - 1, i, -1, 1, min, forwhom);
00191         }
00192         return sum;
00193 }
00194 
00195 static int find_runs (byte *board, int x0, int y0, int dx, int dy, int len,
00196                 int forwhom)
00197         /* OK this function is very ugly. if forwhom is -1 it returns an
00198         * eval of the given line. If not it returns a count forwhom's 
00199         * score on that line, multiplied by RUN_WT */
00200 {
00201         int sum = 0, i, cur = 0; /* cur = current run length */
00202         int x = x0, y = y0;
00203         char prev = -1, cell;
00204         int lopen = 0, ropen = 0; /* can we extend this run in either direction*/
00205         for (i=0; i<len; i++, x += dx, y += dy, prev = cell)
00206         {
00207                 cell = board[y * board_wid + x];
00208                 if (cell == PLOT4_EMPTY)
00209                 {
00210                         cur=0;
00211                         lopen = 1;
00212                         continue;
00213                 }
00214                 if (cell != prev)
00215                         cur = 0;
00216                 cur ++;
00217                 if (i < len - 1 && 
00218                                 board [(y + dy) * board_wid + (x + dx)] == PLOT4_EMPTY)
00219                         ropen = 1;
00220                 else ropen = 0;
00221                 if (cell == PLOT4_WP)
00222                 {
00223                         if (forwhom == -1)
00224                                 sum += ((ropen + lopen) * (cur * cur));
00225                         if (forwhom != BLACK && cur >= 4)
00226                                 sum += RUN_WT;
00227                 }
00228                 if (cell == PLOT4_BP)
00229                 {
00230                         if (forwhom == -1)
00231                                 sum -= ((ropen + lopen) * (cur * cur));
00232                         if (forwhom != WHITE && cur >= 4)
00233                                 sum -= RUN_WT;
00234                 }
00235                 lopen = 0;
00236         }
00237         return sum;
00238 }
00239 
00240 byte * plot4_movegen_single (char *pos, int player, int reset)
00241         /* return a move terminated by -1 */
00242         /* NULL ==> no more moves */
00243 {
00244         static int row;
00245         static byte movbuf[4];
00246         if (reset)
00247                 row = 0;
00248         while (row < board_wid)
00249         {
00250                 int j;
00251                 for (j=board_heit-1; j>=0; j--)
00252                         if (pos[j * board_wid + row] == PLOT4_EMPTY)
00253                         {
00254                                 movbuf[0] = row;
00255                                 movbuf[1] = j;
00256                                 movbuf[2] = (player == WHITE ? PLOT4_WP : PLOT4_BP);
00257                                 movbuf[3] = -1;
00258                                 row++;
00259                                 return movbuf;
00260                         }
00261                 row++;
00262         }
00263         /*movbuf[0] = -1;*/
00264         row = 0;
00265         return NULL;
00266 }
00267 
00269 byte *plot4_movegen (Pos *pos)
00270 {
00271         byte movbuf[256];
00272         byte *movp = movbuf;
00273         byte *movlist;
00274         int i, j;
00275         for (i=0; i<board_wid; i++)
00276         {
00277                 for (j=0; j<board_heit; j++)
00278                         if (pos->board[j * board_wid + i] == PLOT4_EMPTY)
00279                         {
00280                                 *movp++ = i;
00281                                 *movp++ = j;
00282                                 *movp++ = (pos->player == WHITE ? PLOT4_WP : PLOT4_BP);
00283                                 *movp++ = -1;
00284                                 break;
00285                         }
00286         }
00287         *movp++ = -2;
00288         movlist = (byte *) (malloc (movp - movbuf));
00289         memcpy (movlist, movbuf, (movp - movbuf));
00290         return movlist;
00291 }
00292 
00293 char ** plot4_get_pixmap (int idx, int color)
00294 {
00295         int fg, bg, i;
00296         char *colors = plot4_colors;
00297         static char pixbuf[PLOT4_CELL_SIZE*(PLOT4_CELL_SIZE)+1];
00298         if (idx == PLOT4_WP) fg = 0xee << 8;
00299         else if (idx == PLOT4_BP) fg = (0xee << 16) + (0xee << 8);
00300         else fg = 0xd7d7d7;
00301         for(i=0, bg=0;i<3;i++) 
00302         { int col = colors[i]; if (col<0) col += 256; bg += col * (1 << (16-8*i));}
00303         return pixmap_ball_gen(55, pixbuf, fg, bg, 17.0, 30.0);
00304 }
00305