167562Smckusick /* 267562Smckusick * Copyright (c) 1994 367562Smckusick * The Regents of the University of California. All rights reserved. 467562Smckusick * 567562Smckusick * This code is derived from software contributed to Berkeley by 667562Smckusick * Ralph Campbell. 767562Smckusick * 867562Smckusick * %sccs.include.redist.c% 967562Smckusick * 10*69196Smckusick * @(#)gomoku.h 8.2 (Berkeley) 05/03/95 1167562Smckusick */ 1267562Smckusick 1367562Smckusick #include <sys/types.h> 1467562Smckusick 1567562Smckusick /* board dimensions */ 1667562Smckusick #define BSZ 19 1767562Smckusick #define BSZ1 (BSZ+1) 1867562Smckusick #define BSZ2 (BSZ+2) 1967562Smckusick #define BAREA (BSZ2*BSZ1+1) 2067562Smckusick 2167562Smckusick /* frame dimentions (based on 5 in a row) */ 2267562Smckusick #define FSZ1 BSZ 2367562Smckusick #define FSZ2 (BSZ-4) 2467562Smckusick #define FAREA (FSZ1*FSZ2 + FSZ2*FSZ2 + FSZ1*FSZ2 + FSZ2*FSZ2) 2567562Smckusick 2667562Smckusick #define MUP (BSZ1) 2767562Smckusick #define MDOWN (-BSZ1) 2867562Smckusick #define MLEFT (-1) 2967562Smckusick #define MRIGHT (1) 3067562Smckusick 3167562Smckusick /* values for s_occ */ 3267562Smckusick #define BLACK 0 3367562Smckusick #define WHITE 1 3467562Smckusick #define EMPTY 2 3567562Smckusick #define BORDER 3 3667562Smckusick 3767562Smckusick /* return values for makemove() */ 3867562Smckusick #define MOVEOK 0 3967562Smckusick #define RESIGN 1 4067562Smckusick #define ILLEGAL 2 4167562Smckusick #define WIN 3 4267562Smckusick #define TIE 4 4367562Smckusick #define SAVE 5 4467562Smckusick 4567562Smckusick #define A 1 4667562Smckusick #define B 2 4767562Smckusick #define C 3 4867562Smckusick #define D 4 4967562Smckusick #define E 5 5067562Smckusick #define F 6 5167562Smckusick #define G 7 5267562Smckusick #define H 8 5367562Smckusick #define J 9 5467562Smckusick #define K 10 5567562Smckusick #define L 11 5667562Smckusick #define M 12 5767562Smckusick #define N 13 5867562Smckusick #define O 14 5967562Smckusick #define P 15 6067562Smckusick #define Q 16 6167562Smckusick #define R 17 6267562Smckusick #define S 18 6367562Smckusick #define T 19 6467562Smckusick 6567562Smckusick #define PT(x,y) ((x) + BSZ1 * (y)) 6667562Smckusick 6767562Smckusick /* 6867562Smckusick * A 'frame' is a group of five or six contiguous board locations. 6967562Smckusick * An open ended frame is one with spaces on both ends; otherwise, its closed. 7067562Smckusick * A 'combo' is a group of intersecting frames and consists of two numbers: 7167562Smckusick * 'A' is the number of moves to make the combo non-blockable. 7267562Smckusick * 'B' is the minimum number of moves needed to win once it can't be blocked. 7367562Smckusick * A 'force' is a combo that is one move away from being non-blockable 7467562Smckusick * 7567562Smckusick * Single frame combo values: 7667562Smckusick * <A,B> board values 7767562Smckusick * 5,0 . . . . . O 7867562Smckusick * 4,1 . . . . . . 7967562Smckusick * 4,0 . . . . X O 8067562Smckusick * 3,1 . . . . X . 8167562Smckusick * 3,0 . . . X X O 8267562Smckusick * 2,1 . . . X X . 8367562Smckusick * 2,0 . . X X X O 8467562Smckusick * 1,1 . . X X X . 8567562Smckusick * 1,0 . X X X X O 8667562Smckusick * 0,1 . X X X X . 8767562Smckusick * 0,0 X X X X X O 8867562Smckusick * 8967562Smckusick * The rule for combining two combos (<A1,B1> <A2,B2>) 9067562Smckusick * with V valid intersection points, is: 9167562Smckusick * A' = A1 + A2 - 2 - V 9267562Smckusick * B' = MIN(A1 + B1 - 1, A2 + B2 - 1) 9367562Smckusick * Each time a frame is added to the combo, the number of moves to complete 9467562Smckusick * the force is the number of moves needed to 'fill' the frame plus one at 9567562Smckusick * the intersection point. The number of moves to win is the number of moves 9667562Smckusick * to complete the best frame minus the last move to complete the force. 9767562Smckusick * Note that it doesn't make sense to combine a <1,x> with anything since 9867562Smckusick * it is already a force. Also, the frames have to be independent so a 9967562Smckusick * single move doesn't affect more than one frame making up the combo. 10067562Smckusick * 10167562Smckusick * Rules for comparing which of two combos (<A1,B1> <A2,B2>) is better: 10267562Smckusick * Both the same color: 10367562Smckusick * <A',B'> = (A1 < A2 || A1 == A2 && B1 <= B2) ? <A1,B1> : <A2,B2> 10467562Smckusick * We want to complete the force first, then the combo with the 10567562Smckusick * fewest moves to win. 10667562Smckusick * Different colors, <A1,B1> is the combo for the player with the next move: 10767562Smckusick * <A',B'> = A2 <= 1 && (A1 > 1 || A2 + B2 < A1 + B1) ? <A2,B2> : <A1,B1> 10867562Smckusick * We want to block only if we have to (i.e., if they are one move away 10967562Smckusick * from completing a force and we don't have a force that we can 11067562Smckusick * complete which takes fewer or the same number of moves to win). 11167562Smckusick */ 11267562Smckusick 11367562Smckusick #define MAXA 6 11467562Smckusick #define MAXB 2 11567562Smckusick #define MAXCOMBO 0x600 11667562Smckusick 117*69196Smckusick union comboval { 11867562Smckusick struct { 11967562Smckusick #if BYTE_ORDER == BIG_ENDIAN 12067562Smckusick u_char a; /* # moves to complete force */ 12167562Smckusick u_char b; /* # moves to win */ 12267562Smckusick #endif 12367562Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 12467562Smckusick u_char b; /* # moves to win */ 12567562Smckusick u_char a; /* # moves to complete force */ 12667562Smckusick #endif 12767562Smckusick } c; 12867562Smckusick u_short s; 12967562Smckusick }; 13067562Smckusick 13167562Smckusick /* 132*69196Smckusick * This structure is used to record information about single frames (F) and 133*69196Smckusick * combinations of two more frames (C). 134*69196Smckusick * For combinations of two or more frames, there is an additional 135*69196Smckusick * array of pointers to the frames of the combination which is sorted 136*69196Smckusick * by the index into the frames[] array. This is used to prevent duplication 137*69196Smckusick * since frame A combined with B is the same as B with A. 138*69196Smckusick * struct combostr *c_sort[size c_nframes]; 139*69196Smckusick * The leaves of the tree (frames) are numbered 0 (bottom, leftmost) 140*69196Smckusick * to c_nframes - 1 (top, right). This is stored in c_frameindex and 141*69196Smckusick * c_dir if C_LOOP is set. 14267562Smckusick */ 14367562Smckusick struct combostr { 14467562Smckusick struct combostr *c_next; /* list of combos at the same level */ 14567562Smckusick struct combostr *c_prev; /* list of combos at the same level */ 146*69196Smckusick struct combostr *c_link[2]; /* C:previous level or F:NULL */ 147*69196Smckusick union comboval c_linkv[2]; /* C:combo value for link[0,1] */ 148*69196Smckusick union comboval c_combo; /* C:combo value for this level */ 149*69196Smckusick u_short c_vertex; /* C:intersection or F:frame head */ 15067562Smckusick u_char c_nframes; /* number of frames in the combo */ 151*69196Smckusick u_char c_dir; /* C:loop frame or F:frame direction */ 152*69196Smckusick u_char c_flg; /* C:combo flags */ 153*69196Smckusick u_char c_frameindex; /* C:intersection frame index */ 154*69196Smckusick u_char c_framecnt[2]; /* number of frames left to attach */ 155*69196Smckusick u_char c_emask[2]; /* C:bit mask of completion spots for 156*69196Smckusick * link[0] and link[1] */ 157*69196Smckusick u_char c_voff[2]; /* C:vertex offset within frame */ 15867562Smckusick }; 15967562Smckusick 160*69196Smckusick /* flag values for c_flg */ 161*69196Smckusick #define C_OPEN_0 0x01 /* link[0] is an open ended frame */ 162*69196Smckusick #define C_OPEN_1 0x02 /* link[1] is an open ended frame */ 163*69196Smckusick #define C_LOOP 0x04 /* link[1] intersects previous frame */ 164*69196Smckusick #define C_MARK 0x08 /* indicates combo processed */ 16567562Smckusick 166*69196Smckusick /* 167*69196Smckusick * This structure is used for recording the completion points of 168*69196Smckusick * multi frame combos. 169*69196Smckusick */ 17067562Smckusick struct elist { 171*69196Smckusick struct elist *e_next; /* list of completion points */ 172*69196Smckusick struct combostr *e_combo; /* the whole combo */ 173*69196Smckusick u_char e_off; /* offset in frame of this empty spot */ 174*69196Smckusick u_char e_frameindex; /* intersection frame index */ 175*69196Smckusick u_char e_framecnt; /* number of frames left to attach */ 176*69196Smckusick u_char e_emask; /* real value of the frame's emask */ 177*69196Smckusick union comboval e_fval; /* frame combo value */ 17867562Smckusick }; 17967562Smckusick 18067562Smckusick /* 18167562Smckusick * One spot structure for each location on the board. 18267562Smckusick * A frame consists of the combination for the current spot plus the five spots 18367562Smckusick * 0: right, 1: right & down, 2: down, 3: down & left. 18467562Smckusick */ 18567562Smckusick struct spotstr { 18667562Smckusick short s_occ; /* color of occupant */ 18767562Smckusick short s_wval; /* weighted value */ 18867562Smckusick int s_flg; /* flags for graph walks */ 189*69196Smckusick struct combostr *s_frame[4]; /* level 1 combo for frame[dir] */ 190*69196Smckusick union comboval s_fval[2][4]; /* combo value for [color][frame] */ 191*69196Smckusick union comboval s_combo[2]; /* minimum combo value for BLK & WHT */ 19267562Smckusick u_char s_level[2]; /* number of frames in the min combo */ 19367562Smckusick u_char s_nforce[2]; /* number of <1,x> combos */ 194*69196Smckusick struct elist *s_empty; /* level n combo completion spots */ 195*69196Smckusick struct elist *s_nempty; /* level n+1 combo completion spots */ 196*69196Smckusick int dummy[2]; /* XXX */ 19767562Smckusick }; 19867562Smckusick 19967562Smckusick /* flag values for s_flg */ 20067562Smckusick #define CFLAG 0x000001 /* frame is part of a combo */ 20167562Smckusick #define CFLAGALL 0x00000F /* all frame directions marked */ 20267562Smckusick #define IFLAG 0x000010 /* legal intersection point */ 20367562Smckusick #define IFLAGALL 0x0000F0 /* any intersection points? */ 20467562Smckusick #define FFLAG 0x000100 /* frame is part of a <1,x> combo */ 20567562Smckusick #define FFLAGALL 0x000F00 /* all force frames */ 20667562Smckusick #define MFLAG 0x001000 /* frame has already been seen */ 20767562Smckusick #define MFLAGALL 0x00F000 /* all frames seen */ 20867562Smckusick #define BFLAG 0x010000 /* frame intersects border or dead */ 20967562Smckusick #define BFLAGALL 0x0F0000 /* all frames dead */ 21067562Smckusick 211*69196Smckusick /* 212*69196Smckusick * This structure is used to store overlap information between frames. 213*69196Smckusick */ 214*69196Smckusick struct ovlp_info { 215*69196Smckusick int o_intersect; /* intersection spot */ 216*69196Smckusick struct combostr *o_fcombo; /* the connecting combo */ 217*69196Smckusick u_char o_link; /* which link to update (0 or 1) */ 218*69196Smckusick u_char o_off; /* offset in frame of intersection */ 219*69196Smckusick u_char o_frameindex; /* intersection frame index */ 220*69196Smckusick }; 221*69196Smckusick 22267562Smckusick extern char *letters; 22367562Smckusick extern char fmtbuf[]; 224*69196Smckusick extern char pdir[]; 22567562Smckusick 22667562Smckusick extern int dd[4]; 22767562Smckusick extern struct spotstr board[BAREA]; /* info for board */ 228*69196Smckusick extern struct combostr frames[FAREA]; /* storage for single frames */ 22967562Smckusick extern struct combostr *sortframes[2]; /* sorted, non-empty frames */ 230*69196Smckusick extern u_char overlap[FAREA * FAREA]; /* frame [a][b] overlap */ 23167562Smckusick extern short intersect[FAREA * FAREA]; /* frame [a][b] intersection */ 23267562Smckusick extern int movelog[BSZ * BSZ]; /* history of moves */ 23367562Smckusick extern int movenum; 23467562Smckusick extern int debug; 23567562Smckusick 23667562Smckusick extern char *copy(); 23767562Smckusick extern char *stoc(); 23867562Smckusick extern char *tail(); 23967562Smckusick 24067562Smckusick #define ASSERT(x) 241