|
|
#include <windows.h>
#include <port1632.h>
#include <process.h>
#include <stdlib.h>
#include "reversi.h"
VOID NEAR PASCAL paintmove(BYTE b[BoardSize], INT move, INT friendly, INT enemy); BOOL NEAR PASCAL msgcheck(VOID);
extern INT moves[61]; extern INT BestMove[max_depth+2]; extern HWND hWin; extern HDC hDisp; extern INT depth; extern INT direc[];
/* Indexes for computing scores and whether or not a player has */ /* any pieces on the board. Very order dependant. */
BYTE PieceFlags[] = { 0x00 , /* Ignore sides */ 0x00 , /* Ignore blanks */ 0x01 , /* Human has a piece */ 0x02 , /* Computer has a piece */ };
INT Scores[] = { 0, 0 }; INT humanScore = 0; INT compScroe = 0;
BYTE FinalComp[] = {0, 0, -1, 1 }; /* Table for compute # computer pieces */
BYTE FinalHuman[] = {0, 0, 1, -1}; /* Table for compute # human pieces */
/*
* The scoring tables are used to evaluate the board * position. The corners of the board change value * according to whether a given square is occupied or * not. This can be done dynamically, saving ~ 1K * worth of data space but costing an as of yet * undetermined performance hit. */
#define B11 11 /* Offsets to particular squares */
#define B18 18
#define B81 81
#define B88 88
#define maskb11 0x08 /* Masks used for indexing into Scoring tables. */
#define maskb18 0x04
#define maskb81 0x02
#define maskb88 0x01
INT NEAR PASCAL finalscore( BYTE b[], BYTE friendly, BYTE enemy) { INT i; INT count=0;
for (i=11 ; i<=88 ; i++) { if (b[i] == friendly) count++; else if (b[i] == enemy) count--; } if (count > 0) return(win + count); else if (count < 0) return(loss + count); else return(0); }
INT NEAR PASCAL legalcheck( BYTE b[], INT move, BYTE friendly, BYTE enemy) { INT sq,d; INT *p;
if (b[move] == empty) { p=direc; while ((d = *p++) != 0) { sq=move; if (b[sq += d] == enemy) { while(b[sq += d] == enemy) ; if (b[sq] == friendly) return(1); } } } return(0); }
VOID NEAR PASCAL makemove( BYTE b[], INT move, BYTE friendly, BYTE enemy) { INT sq,d; INT *p;
if (move != PASS) { p=direc; while ((d = *p++) != 0) { sq=move; if (b[sq += d] == enemy) { while(b[sq += d] == enemy) ; if (b[sq] == friendly) while(b[sq -= d] == enemy) b[sq]=friendly; } } b[move]=friendly; } }
/*
calculate the value of board
*/ INT NEAR PASCAL score( BYTE b[], BYTE friendly, BYTE enemy) { INT *pvalue; BYTE *pb; INT fpoints=0; INT epoints=0; INT ecount=0; BYTE bv; INT v,b11,b18,b81,b88;
static INT value[79] = { 99, -8, 8, 6, 6, 8, -8, 99,000, 000, -8,-24, -4, -3, -3, -4,-24, -8,000, 000, 8, -4, 7, 4, 4, 7, -4, 8,000, 000, 6, -3, 4, 0, 0, 4, -3, 6,000, 000, 6, -3, 4, 0, 0, 4, -3, 6,000, 000, 8, -4, 7, 4, 4, 7, -4, 8,000, 000, -8,-24, -4, -3, -3, -4,-24, -8,000, 000, 99, -8, 8, 6, 6, 8, -8, 99,infin};
static INT value2[79]= { 99, -8, 8, 6, 6, 8, -8, 99,000, 000, -8,-24, 0, 1, 1, 0,-24, -8,000, 000, 8, 0, 7, 4, 4, 7, 0, 8,000, 000, 6, 1, 4, 1, 1, 4, 1, 6,000, 000, 6, 1, 4, 1, 1, 4, 1, 6,000, 000, 8, 0, 7, 4, 4, 7, 0, 8,000, 000, -8,-24, 0, 1, 1, 1,-24, -8,000, 000, 99, -8, 8, 6, 6, 8, -8, 99,infin};
pb = &b[11]; b11 = *pb; b18 = b[18]; b81 = b[81]; b88 = b[88];
if ((b11 != empty) || (b18 != empty) || (b81 != empty) || (b88 != empty)) { pvalue = value2;
if (b11 == empty) { value2[12-11] = -8; value2[21-11] = -8; value2[22-11] = -24; } else { value2[12-11] = 12; value2[21-11] = 12; value2[22-11] = 8; }
if (b18 == empty) { value2[17-11] = -8; value2[28-11] = -8; value2[27-11] = -24; } else { value2[17-11] = 12; value2[28-11] = 12; value2[27-11] = 8; }
if (b81 == empty) { value2[82-11] = -8; value2[71-11] = -8; value2[72-11] = -24; } else { value2[82-11] = 12; value2[71-11] = 12; value2[72-11] = 8; }
if (b88 == empty) { value2[87-11] = -8; value2[78-11] = -8; value2[77-11] = -24; } else { value2[87-11] = 12; value2[78-11] = 12; value2[77-11] = 8; } } else { pvalue = value; }
while((v=*pvalue++) != infin) { bv = *pb++; if (bv == friendly) fpoints += v; else if (bv == enemy) { epoints += v; ecount++; }
} if (!ecount) /* any enemy pieces on the board? */ return(win); /* if not, we just won! */ else return(fpoints-epoints); }
INT NEAR PASCAL minmax( BYTE b[max_depth + 2][100], INT move, BYTE friendly, BYTE enemy, INT ply, INT vmin, INT vmax) { BYTE *pCurrent, *pPrevious, *pSource, *pDest; INT *pMoves; INT *pBestMove; INT i; INT sq, value, cur_move;
pPrevious = &b[ply][0]; pCurrent = &b[ply+1][0];
pSource = &b[ply][11]; pDest = &b[ply+1][11]; for (i=11 ; i<=88 ; i++) *pDest++=*pSource++;
pBestMove = &BestMove[ply]; if (move == PASS) { if (ply == depth) { pMoves = moves; while((sq = *pMoves++) != 0) { if (legalcheck(pCurrent,sq,enemy,friendly)) return(score(pCurrent,friendly,enemy)); } return(finalscore(pCurrent,friendly,enemy)); } } else { if (ply == 0) { hDisp = GetDC(hWin); paintmove(pCurrent,move,friendly,enemy); ReleaseDC(hWin, hDisp); } else { makemove(pCurrent,move,friendly,enemy); if (ply == depth) return(score(pCurrent,friendly,enemy)); } } pMoves = moves; cur_move = PASS; *pBestMove = PASS; while((sq = *pMoves++) != 0) { if (legalcheck(pCurrent,sq,enemy,friendly)) { cur_move = sq; value = minmax(b,cur_move,enemy,friendly,ply+1,-vmax,-vmin); if (value > vmin) { vmin = value; *pBestMove = cur_move; if (value >= vmax) goto cutoff; /* alpha-beta cutoff */ } } } if (cur_move == PASS) { if (move == PASS) /* two passes in a row mean game is over */ return(finalscore(pCurrent,friendly,enemy)); else { value = minmax(b,PASS,enemy,friendly,ply+1,-vmax,-vmin); if (value > vmin) vmin = value; } } cutoff: return(-vmin); }
|