📄 pressup.c
字号:
while (!move_selected) {
if (chg_flag) { /* avoid unneccessary updates */
print_square(&master, row, col, TRUE);
refresh();
chg_flag = FALSE;
}
cmd = getch();
if (islower(cmd)) {
cmd = toupper(cmd);
}
rd = cd = 0;
switch(cmd) {
default: /* Unknown command */
BEEP();
break;
case ERR: /* Problem or non-blocking getch() */
break;
case ' ': /* select current position */
m = row*Side + col;
if (star < 0) { /* first move */
if (master.board[m] == 0) {
move_selected = TRUE;
} else {
BEEP();
}
} else {
dr = abs(row - star/Side);
dc = abs(col - star%Side);
if (master.board[m] < 3 && dr < 2 && dc < 2) {
move_selected = TRUE;
} else {
BEEP();
}
}
break;
case 'H': /* move left */
if (col == 0) {
BEEP();
} else {
cd = -1;
}
break;
case 'J' :
if (row == Side-1) {
BEEP();
} else {
rd = 1;
}
break;
case 'K' :
if (row == 0) {
BEEP();
} else {
rd = -1;
}
break;
case 'L': /* move right */
if (col == Side-1) {
BEEP();
} else {
cd = 1;
}
break;
case 'Q': /* user wants to quit */
m = -1;
move_selected = TRUE;
break;
case 'Z': /* He wants help ... */
m = Help();
move_selected = TRUE;
break;
}
if (rd != 0 || cd != 0) {
print_square(&master, row, col, FALSE);
row += rd; col += cd;
chg_flag = TRUE;
}
}
return m;
}
/*
* Routine: Help
*
* Description: Give the poor soul some badly needed assistance
*
*/
int Help()
{
move(BOARDY+Side+1, STATUSX);
addstr("I'm thinking for you...");
Helpflag = 1;
search(&master,Depth,-1,-32000,-32000);
return BestMove;
}
/*
* Routine: main
*
* Description: ...
*
*/
int main(argc, argv)
int argc;
char *argv[];
{
int ch; /* option char from argv */
int errflag; /* TRUE if something went wrong in arg parsing */
int i,j;
FFlag = BFlag = 0;
image = ".rbXRB";
Depth = 3;
errflag = FALSE;
/* Do getopt instead: */
while ((ch =getopt(argc, argv, "bd:f")) != EOF) {
switch(ch) {
default : /* unknown value returned from getopt() */
fprintf(stderr, "fatal: unknown value returned from getopt(): %x\n",
ch);
exit(EXIT_FAILURE);
case '?': /* unknown option letter - errmsg already printed */
errflag = TRUE;
break;
case 'b':
BFlag++;
break;
case 'd': /* depth of search tree */
Depth = (int) strtol(optarg, (char **)0, 0);
break;
case 'f':
FFlag++;
break;
}
}
if (optind < argc) {
fprintf(stderr, "unknown argument -- '%s'\n", argv[optind]);
errflag = TRUE;
}
if (errflag) {
fprintf(stderr, "usage: pressup [-b] [-d depth] [-f]\n");
exit(EXIT_FAILURE);
}
initscr();
cbreak();
noecho();
ngame:
Startflag = 1;
Helpflag = 0;
for (i=0; i<(Side*Side); i++) initb.board[i] = 0;
for (j=1; j<(Side-1); j++) {
initb.board[j] = 1;
initb.board[(Side*Side-1)-j] = 1;
initb.board[Side*j] = 2;
initb.board[Side*j + Side-1] = 2;
};
initb.star = -1; initb.red = 0; initb.blue = 0;
boardcopy(&initb, &master);
pboard(&master);
boardcopy(&master, &savebd);
for(;;) {
if (FFlag) {
FFlag = 0;
goto Mine;
}
if (CheckWin(&master)) {
asknew();
goto ngame;
}
i = getmove();
if (i < 0) {
move(BOARDY+Side+3, STATUSX);
addstr("You quit! ");
asknew();
goto ngame;
}
dmove(i);
if (CheckWin(&master)) {
asknew();
goto ngame;
}
Mine:
move(BOARDY+Side+1, STATUSX);
addstr("I'm thinking... ");
i = search(&master, Depth, 1, -32000, -32000);
if (BFlag) {
move(EVALX, EVALY); printw("Pos. eval = %4d", i);
}
dmove(BestMove);
if (i > 500) {
move(STATUSY+1, STATUSX); addstr("I've got you!");
}
if (i < -500) {
move(STATUSY+1, STATUSX); addstr("You've got me!");
}
}
/*NOTREACHED*/ /* asknew() exits */
}
/*
* Routine: mmove
*
* Description: Make a move
*
*/
void mmove(bp,n)
BBOARD *bp;
int n;
{
int type;
type = bp->board[n] += 3;
if (type == 4) bp->red++;
else if (type == 5) bp->blue++;
bp->star = n;
}
/*
* Routine: pboard
*
* Description: Update screen with new board, status, and everything.
*
*/
void pboard(bp)
BBOARD *bp;
{
int row, col; /* Board coordinates */
/* 1. Program name and version: */
move(HDRY, HDRX); addstr(HDR);
/* 2. Board: */
for (row=0; row<Side; row++) {
for (col=0; col<Side; col++) {
print_square(bp, row, col, FALSE);
}
}
/* 3. Print score, search depth and other info: */
move(DEPTHY, DEPTHX);
printw("Search Depth: %2d moves", Depth);
move(SCOREY, SCOREX);
printw("Score: Blue (me) %2d, Red (you) %2d", master.blue, master.red);
if (Helpflag) {
move(HELPY, HELPX);
addstr("You've had help!");
}
if (Startflag) {
move(STARTY, STARTX);
addstr(FFlag ? "I go first" : "You go first");
Startflag = 0;
}
}
/*
* Routine: print_square
*
* Description: Print a square on the given board.
*
*/
void print_square(bp, row, col, invert)
BBOARD *bp;
int row;
int col;
int invert;
{
int n; /* internal coordinate */
move(BOARDY+row, BOARDX+3*col); /* Each square is 3 char wide */
if (invert) {
standout();
}
n = row*Side + col;
if (bp->star == n) {
addstr(" * ");
} else {
printw(" %c ", image[bp->board[n]]);
}
if (invert) {
standend();
}
/*
* Leave cursor *on* square.
* This is quite good for systems with line cursors. Non-blinking
* block cursors give a rather odd impression, though.
*
*/
move(BOARDY+row, BOARDX+3*col+1);
}
/*
* Routine: search
*
* Description: Alpha-beta pruning search
*
* Put best move for 'who' into BestMove. Return
* estimated strength of position.
*
*/
int search (bp,ddepth,who,alpha,beta)
BBOARD *bp;
int ddepth;
int who;
int alpha;
int beta;
{
int i,j,k;
int myalpha,hisalpha;
int best;
int num;
int bestmove, ii, jj, n;
int SavStar;
int SavBlue;
int SavRed;
int Save;
char moves[9];
best = -32000;
SavStar = bp->star;
SavBlue = bp->blue;
SavRed = bp->red;
BestMove = -1; /* No best move yet... */
if (SavStar < 0) { /* special case opening moves */
BestMove = HISFIRST;
if (who > 0) BestMove = MYFIRST;
return 0;
};
if (!ddepth--)
return(who * (bp->blue - bp->red));
if (bp->blue == (Side*2-4) || bp->red == (Side*2-4))
return(who*(bp->blue - bp->red)*1000);
/* alpha-beta pruning */
if (who>0) {
myalpha = bp->blue; hisalpha = bp->red;
} else {
myalpha = bp->red; hisalpha = bp->blue;
}
myalpha += ddepth; /* Most optimistic estimate. */
if (myalpha > (Side*2-4)) myalpha = (Side*2-4);
if (myalpha == (Side*2-4)) myalpha = 1000*(myalpha-hisalpha);
else myalpha -= hisalpha;
if (myalpha <= alpha) return best;
k = bp->star;
i = k%Side;
j = k/Side;
num = 0;
for (n=0; n<8; n++) { /* Try squares 'around' last move */
if ((ii = i+Adj[n+n]) < 0 || ii >= Side) continue;
if ((jj = j+Adj[n+n+1]) < 0 || jj >= Side) continue;
moves[num] = jj*Side + ii;
if (bp->board[moves[num]] < 3) num++;
}
if (num == 0) return(who*(bp->blue - bp->red)*1000);
bestmove = moves[0];
for (i=0; i<num; i++) {
Save = bp->board[moves[i]];
mmove(bp,moves[i]);
k = -search(bp,ddepth,-who,beta,alpha);
bp->board[moves[i]] = Save;
bp->blue = SavBlue; bp->red = SavRed; bp->star = SavStar;
if (k > alpha) alpha = k;
if (k > best) { best = k; bestmove = moves[i]; }
if (k>100) break;
}
BestMove = bestmove;
return best;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -