diff options
Diffstat (limited to 'mbbsd/othello.c')
-rw-r--r-- | mbbsd/othello.c | 427 |
1 files changed, 230 insertions, 197 deletions
diff --git a/mbbsd/othello.c b/mbbsd/othello.c index 4a146f77..76cd2f8c 100644 --- a/mbbsd/othello.c +++ b/mbbsd/othello.c @@ -1,4 +1,4 @@ -/* $Id: othello.c,v 1.3 2002/06/04 13:08:34 in2 Exp $ */ +/* $Id: othello.c,v 1.4 2002/07/05 17:10:27 in2 Exp $ */ #include "bbs.h" #define LOGFILE "etc/othello.log" @@ -20,67 +20,71 @@ #define INVERT(COLOR) (((COLOR))==WHITE?BLACK:WHITE) -static char nowx = 3, nowy = 3; -static char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; -static char DIRX[] = {-1,-1,-1, 0, 1, 1, 1, 0}; -static char DIRY[] = {-1, 0, 1, 1, 1, 0,-1,-1}; -static char number[2]; - -static char pass = 0; -static char if_hint = 0; -static int think, which_table; - -static char nowboard[10][10]= -{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, - {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; -static char init_table[NR_TABLE+1][5][5] = { - {{ 0, 0, 0, 0, 0}, - { 0,30,-3, 2, 2}, - { 0,-3,-3,-1,-1}, - { 0, 2,-1, 1, 1}, - { 0, 2,-1, 1, 0}}, - - {{ 0, 0, 0, 0, 0}, - { 0,70, 5,20,30}, - { 0, 5,-5, 3, 3}, - { 0,20, 3, 5, 5}, - { 0,30, 3, 5, 5}}, - - {{ 0, 0, 0, 0, 0}, - { 0, 5, 2, 2, 2}, - { 0, 2, 1, 1, 1}, - { 0, 2, 1, 1, 1}, - { 0, 2, 1, 1, 1}} +static char nowx = 3, nowy = 3; +static char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS}; +static char DIRX[] = {-1, -1, -1, 0, 1, 1, 1, 0}; +static char DIRY[] = {-1, 0, 1, 1, 1, 0, -1, -1}; +static char number[2]; + +static char pass = 0; +static char if_hint = 0; +static int think, which_table; + +static char nowboard[10][10] = +{{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, -1}, +{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}; +static char init_table[NR_TABLE + 1][5][5] = { + {{0, 0, 0, 0, 0}, + {0, 30, -3, 2, 2}, + {0, -3, -3, -1, -1}, + {0, 2, -1, 1, 1}, + {0, 2, -1, 1, 0}}, + + {{0, 0, 0, 0, 0}, + {0, 70, 5, 20, 30}, + {0, 5, -5, 3, 3}, + {0, 20, 3, 5, 5}, + {0, 30, 3, 5, 5}}, + + {{0, 0, 0, 0, 0}, + {0, 5, 2, 2, 2}, + {0, 2, 1, 1, 1}, + {0, 2, 1, 1, 1}, + {0, 2, 1, 1, 1}} }; -static char table[NR_TABLE + 1][10][10]; -static void print_chess(int x, int y, char chess) { +static char table[NR_TABLE + 1][10][10]; +static void +print_chess(int x, int y, char chess) +{ move(STARTX - 1 + x * 2, STARTY - 2 + y * 4); - if(chess != HINT || if_hint == 1) + if (chess != HINT || if_hint == 1) prints(CHESS_TYPE[(int)chess]); else prints(CHESS_TYPE[NONE]); refresh(); } -static void printboard() { - int i; - +static void +printboard() +{ + int i; + move(STARTX, STARTY); prints("┌─┬─┬─┬─┬─┬─┬─┬─┐"); - for(i = 0; i < 7; i++) { + for (i = 0; i < 7; i++) { move(STARTX + 1 + i * 2, STARTY); - prints ("│ │ │ │ │ │ │ │ │"); + prints("│ │ │ │ │ │ │ │ │"); move(STARTX + 2 + i * 2, STARTY); - prints ("├─┼─┼─┼─┼─┼─┼─┼─┤"); + prints("├─┼─┼─┼─┼─┼─┼─┼─┤"); } move(STARTX + 1 + i * 2, STARTY); prints("│ │ │ │ │ │ │ │ │"); @@ -91,7 +95,7 @@ static void printboard() { print_chess(4, 5, BLACK); print_chess(5, 4, BLACK); move(3, 56); - prints("(黑)%s",cuser.userid); + prints("(黑)%s", cuser.userid); move(3, 72); prints(": 02"); move(4, 56); @@ -102,7 +106,7 @@ static void printboard() { prints("[q] 退出"); move(8, 56); prints("[h] 開啟/關閉 提示"); - move(9,56); + move(9, 56); prints("[Enter][Space] 下棋"); move(10, 56); prints("上:↑, i"); @@ -114,39 +118,43 @@ static void printboard() { prints("右:→, l"); } -static int get_key(char nowx, char nowy) { - int ch; - +static int +get_key(char nowx, char nowy) +{ + int ch; + move(STARTX - 1 + nowx * 2, STARTY - 1 + nowy * 4); ch = igetkey(); move(STARTX - 1 + nowx * 2, STARTY - 2 + nowy * 4); - if(nowboard[(int)nowx][(int)nowy] != HINT || if_hint==1) + if (nowboard[(int)nowx][(int)nowy] != HINT || if_hint == 1) outs(CHESS_TYPE[(int)nowboard[(int)nowx][(int)nowy]]); else outs(CHESS_TYPE[NONE]); return ch; } -static int eatline(int i, int j, char color, int dir, char chessboard[][10]) { - int tmpx,tmpy; - char tmpchess; - +static int +eatline(int i, int j, char color, int dir, char chessboard[][10]) +{ + int tmpx, tmpy; + char tmpchess; + tmpx = i + DIRX[dir]; tmpy = j + DIRY[dir]; tmpchess = chessboard[tmpx][tmpy]; - if(tmpchess == -1) + if (tmpchess == -1) return false; - if(tmpchess != INVERT(color)) + if (tmpchess != INVERT(color)) return false; - + tmpx += DIRX[dir]; tmpy += DIRY[dir]; tmpchess = chessboard[tmpx][tmpy]; - while(tmpchess != -1) { - if(tmpchess < BLACK) + while (tmpchess != -1) { + if (tmpchess < BLACK) return false; - if(tmpchess == color) { - while(i != tmpx || j != tmpy) { + if (tmpchess == color) { + while (i != tmpx || j != tmpy) { chessboard[i][j] = color; i += DIRX[dir]; j += DIRY[dir]; @@ -160,32 +168,36 @@ static int eatline(int i, int j, char color, int dir, char chessboard[][10]) { return false; } -static int if_can_put(int x, int y, char color, char chessboard[][10]) { - int i, temp, checkx, checky; - - if(chessboard[x][y]<BLACK) - for(i = 0; i < 8; i++) { +static int +if_can_put(int x, int y, char color, char chessboard[][10]) +{ + int i, temp, checkx, checky; + + if (chessboard[x][y] < BLACK) + for (i = 0; i < 8; i++) { checkx = x + DIRX[i]; checky = y + DIRY[i]; temp = chessboard[checkx][checky]; - if(temp < BLACK) + if (temp < BLACK) continue; - if(temp != color) - while(chessboard[checkx += DIRX[i]][checky += DIRY[i]] > HINT) - if(chessboard[checkx][checky] == color) + if (temp != color) + while (chessboard[checkx += DIRX[i]][checky += DIRY[i]] > HINT) + if (chessboard[checkx][checky] == color) return true; } return false; } -static int get_hint(char color) { - int i, j, temp = 0; - - for(i = 1; i <= 8; i++) - for(j = 1; j <= 8; j++) { - if(nowboard[i][j] == HINT) +static int +get_hint(char color) +{ + int i, j, temp = 0; + + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) { + if (nowboard[i][j] == HINT) nowboard[i][j] = NONE; - if(if_can_put(i, j, color, nowboard)) { + if (if_can_put(i, j, color, nowboard)) { nowboard[i][j] = HINT; temp++; } @@ -194,89 +206,96 @@ static int get_hint(char color) { return temp; } -static void eat(int x, int y, int color, char chessboard[][10]) { - int k; - - for(k = 0; k < 8; k++) +static void +eat(int x, int y, int color, char chessboard[][10]) +{ + int k; + + for (k = 0; k < 8; k++) eatline(x, y, color, k, chessboard); } -static void end_of_game(int quit) { - FILE *fp,*fp1; - char *opponent[] = {"","CD-65","","嬰兒","小孩","","大人","專家"}; - +static void +end_of_game(int quit) +{ + FILE *fp, *fp1; + char *opponent[] = {"", "CD-65", "", "嬰兒", "小孩", "", "大人", "專家"}; + move(STARTX - 1, 30); - prints (" "); + prints(" "); move(22, 35); fp = fopen(LOGFILE, "a"); - if(!quit) { + if (!quit) { fp1 = fopen(SECRET, "a"); - if(fp1) { + if (fp1) { fprintf(fp1, "%d,%d,%s,%02d,%02d\n", think, which_table, - cuser.userid, number[0], number[1]); + cuser.userid, number[0], number[1]); fclose(fp1); } } - - if(quit) { - if(number[0] == 2 && number[1] == 2) { - if(fp) + if (quit) { + if (number[0] == 2 && number[1] == 2) { + if (fp) fclose(fp); return; } fprintf(fp, "在%s級中, %s臨陣脫逃\n", opponent[think], cuser.userid); - if(fp) - fclose(fp); + if (fp) + fclose(fp); return; - } - if(number[0] > number[1]) { + } + if (number[0] > number[1]) { prints("你贏了電腦%02d子", number[0] - number[1]); - if(think == 6 && number[0] - number[1] >= 50) + if (think == 6 && number[0] - number[1] >= 50) demoney(200); - if(think == 7 && number[0] - number[1] >= 40) + if (think == 7 && number[0] - number[1] >= 40) demoney(200); - if(fp) + if (fp) fprintf(fp, "在%s級中, %s以 %02d:%02d 贏了電腦%02d子\n", opponent[think], cuser.userid, number[0], number[1], number[0] - number[1]); - } else if(number[1] > number[0]) { + } else if (number[1] > number[0]) { prints("電腦贏了你%02d子", number[1] - number[0]); - if(fp) { + if (fp) { fprintf(fp, "在%s級中, ", opponent[think]); - if(number[1] - number[0] > 20) + if (number[1] - number[0] > 20) fprintf(fp, "電腦以 %02d:%02d 慘電%s %02d子\n", number[1], number[0], cuser.userid, number[1] - number[0]); else fprintf(fp, "電腦以 %02d:%02d 贏了%s %02d子\n", number[1], number[0], cuser.userid, number[1] - number[0]); - } + } } else { prints("你和電腦打成平手!!"); - if(fp) + if (fp) fprintf(fp, "在%s級中, %s和電腦以 %02d:%02d 打成了平手\n", opponent[think], cuser.userid, number[1], number[0]); } - if(fp) + if (fp) fclose(fp); - move(1,1); + move(1, 1); igetkey(); } -static void othello_redraw() { - int i, j; - - for(i = 1; i <= 8; i++) - for(j = 1; j <= 8; j++) +static void +othello_redraw() +{ + int i, j; + + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) print_chess(i, j, nowboard[i][j]); } -static int player(char color) { - int ch; - - if(get_hint(color)) { - while(true) { - ch = get_key(nowx,nowy); - switch(ch) { +static int +player(char color) +{ + int ch; + + if (get_hint(color)) { + while (true) { + ch = get_key(nowx, nowy); + switch (ch) { case 'J': case 'j': case KEY_LEFT: @@ -296,10 +315,10 @@ static int player(char color) { case 'k': case KEY_DOWN: nowx++; - break; + break; case ' ': case '\r': - if(nowboard[(int)nowx][(int)nowy] != HINT) + if (nowboard[(int)nowx][(int)nowy] != HINT) break; pass = 0; nowboard[(int)nowx][(int)nowy] = color; @@ -311,26 +330,26 @@ static int player(char color) { return false; case 'H': case 'h': - if_hint = if_hint^1; + if_hint = if_hint ^ 1; othello_redraw(); break; } - if(nowx == 9) - nowx=1; - if(nowx == 0) - nowx=8; - if(nowy == 9) - nowy=1; - if(nowy == 0) - nowy=8; + if (nowx == 9) + nowx = 1; + if (nowx == 0) + nowx = 8; + if (nowy == 9) + nowy = 1; + if (nowy == 0) + nowy = 8; } } else { pass++; - if(pass == 1) { + if (pass == 1) { move(23, 34); prints("你必需放棄這一步!!"); igetch(); - move(28,23); + move(28, 23); prints(" "); } else { end_of_game(0); @@ -340,35 +359,39 @@ static int player(char color) { return 0; } -static void init() { - int i, j, i1, j1; - +static void +init() +{ + int i, j, i1, j1; + nowx = 4; nowy = 4; number[0] = number[1] = 2; - for(i = 1; i <= 8; i++) - for(j = 1;j <= 8; j++) { + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) { i1 = 4.5 - abs(4.5 - i); j1 = 4.5 - abs(4.5 - j); table[0][i][j] = init_table[0][i1][j1]; table[1][i][j] = init_table[1][i1][j1]; } - for(i = 1; i <= 8; i++) - for(j = 1; j <= 8; j++) + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) nowboard[i][j] = NONE; nowboard[4][4] = nowboard[5][5] = WHITE; nowboard[4][5] = nowboard[5][4] = BLACK; } -static void report() { - int i, j; - +static void +report() +{ + int i, j; + number[0] = number[1] = 0; - for(i = 1; i <= 8; i++) - for(j = 1; j <= 8; j++) - if(nowboard[i][j] == BLACK) + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) + if (nowboard[i][j] == BLACK) number[0]++; - else if(nowboard[i][j] == WHITE) + else if (nowboard[i][j] == WHITE) number[1]++; move(3, 60); prints("%s", cuser.userid); @@ -378,12 +401,14 @@ static void report() { prints("電腦 : %02d", number[1]); } -static int EVL(char chessboard[][10], int color, int table_number) { - int points = 0,a,b; - for(a = 1; a <= 8; a++) - for(b = 1; b <= 8; b++) - if(chessboard[a][b] > HINT) { - if(chessboard[a][b] == BLACK) +static int +EVL(char chessboard[][10], int color, int table_number) +{ + int points = 0, a, b; + for (a = 1; a <= 8; a++) + for (b = 1; b <= 8; b++) + if (chessboard[a][b] > HINT) { + if (chessboard[a][b] == BLACK) points += table[table_number][a][b]; else points -= table[table_number][a][b]; @@ -391,57 +416,61 @@ static int EVL(char chessboard[][10], int color, int table_number) { return ((color == BLACK) ? points : -points); } -static int alphabeta(int alpha, int beta, int level, char chessboard[][10], - int thinkstep, int color, int table) { - int i, j, k, flag = 1; - char tempboard[10][10]; - if(level == thinkstep+1) +static int +alphabeta(int alpha, int beta, int level, char chessboard[][10], + int thinkstep, int color, int table) +{ + int i, j, k, flag = 1; + char tempboard[10][10]; + if (level == thinkstep + 1) return EVL(chessboard, (level & 1 ? color : ((color - 2) ^ 1) + 2), table); - for(i = 1; i <= 8; i++) { - for(j = 1; j <= 8; j++) { - if(if_can_put(i, j, color, chessboard)) { + for (i = 1; i <= 8; i++) { + for (j = 1; j <= 8; j++) { + if (if_can_put(i, j, color, chessboard)) { flag = 0; memcpy(tempboard, chessboard, sizeof(char) * 100); eat(i, j, color, tempboard); - + k = alphabeta(alpha, beta, level + 1, tempboard, thinkstep, ((color - 2) ^ 1) + 2, table); - if(((level & 1) && k > alpha)) + if (((level & 1) && k > alpha)) alpha = k; - else if(!(level & 1) && k < beta) + else if (!(level & 1) && k < beta) beta = k; - if(alpha >= beta) + if (alpha >= beta) break; } } } - if(flag) + if (flag) return EVL(chessboard, color, table); return ((level & 1) ? alpha : beta); } -static int Computer(int thinkstep, int table) { - int i, j, maxi = 0, maxj = 0, level = 1; - char chessboard[10][10]; - int alpha = -10000, k; - if((number[0] + number[1]) > 44) +static int +Computer(int thinkstep, int table) +{ + int i, j, maxi = 0, maxj = 0, level = 1; + char chessboard[10][10]; + int alpha = -10000, k; + if ((number[0] + number[1]) > 44) table = NR_TABLE; - for(i = 1; i <= 8; i++) - for(j = 1; j <= 8; j++) { - if(if_can_put(i,j,WHITE,nowboard)) { + for (i = 1; i <= 8; i++) + for (j = 1; j <= 8; j++) { + if (if_can_put(i, j, WHITE, nowboard)) { memcpy(chessboard, nowboard, sizeof(char) * 100); eat(i, j, WHITE, chessboard); k = alphabeta(alpha, 10000, level + 1, chessboard, thinkstep, BLACK, table); - if(k > alpha) { + if (k > alpha) { alpha = k; maxi = i; maxj = j; } } } - if(alpha != -10000) { + if (alpha != -10000) { eat(maxi, maxj, WHITE, nowboard); pass = 0; nowx = maxi; @@ -450,7 +479,7 @@ static int Computer(int thinkstep, int table) { move(23, 30); prints("電腦放棄這一步棋!!"); pass++; - if(pass == 2) { + if (pass == 2) { move(23, 24); prints(" "); end_of_game(0); @@ -458,26 +487,28 @@ static int Computer(int thinkstep, int table) { } igetch(); move(23, 24); - prints(" "); + prints(" "); } return true; } -static int choose() { - char thinkstep[2]; - +static int +choose() +{ + char thinkstep[2]; + move(2, 0); prints("請選擇難度:"); move(5, 0); - prints("(1) CD-65\n"); /* 想 1 步 */ - prints("(2) 嬰兒\n"); /* 想 3 步 */ - prints("(3) 小孩\n"); /* 想 4 步 */ + prints("(1) CD-65\n"); /* 想 1 步 */ + prints("(2) 嬰兒\n"); /* 想 3 步 */ + prints("(3) 小孩\n"); /* 想 4 步 */ do { getdata(4, 0, "請選擇一個對象和您對打:(1~5)", thinkstep, sizeof(thinkstep), LCECHO); - } while(thinkstep[0] < '1' || thinkstep[0] > '3'); + } while (thinkstep[0] < '1' || thinkstep[0] > '3'); clear(); - switch(thinkstep[0]) { + switch (thinkstep[0]) { case '2': thinkstep[0] = '3'; break; @@ -493,33 +524,35 @@ static int choose() { #define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0 -int othello_main() { +int +othello_main() +{ lockreturn0(OTHELLO, LOCK_MULTI); clear(); init(); think = choose(); - showtitle("黑白棋", BBSName); + showtitle("黑白棋", BBSName); printboard(); which_table = rand() % NR_TABLE; - while(true) { + while (true) { move(STARTX - 1, 30); prints("輪到你下了..."); - if(!player(BLACK)) + if (!player(BLACK)) break; report(); othello_redraw(); - if(number[0] + number[1] == 64) { + if (number[0] + number[1] == 64) { end_of_game(0); break; } move(STARTX - 1, 30); prints("電腦思考中..."); refresh(); - if(!Computer(think, which_table)) + if (!Computer(think, which_table)) break; report(); othello_redraw(); - if(number[0] + number[1] == 64) { + if (number[0] + number[1] == 64) { end_of_game(0); break; } |