summaryrefslogtreecommitdiffstats
path: root/mbbsd/othello.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbbsd/othello.c')
-rw-r--r--mbbsd/othello.c568
1 files changed, 0 insertions, 568 deletions
diff --git a/mbbsd/othello.c b/mbbsd/othello.c
deleted file mode 100644
index 27e385dc..00000000
--- a/mbbsd/othello.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/* $Id$ */
-#include "bbs.h"
-
-#define LOGFILE "etc/othello.log"
-#define NR_TABLE 2
-
-#define true 1
-#define false 0
-#define STARTX 3
-#define STARTY 20
-#define NONE_CHESS " "
-#define WHITE_CHESS "●"
-#define BLACK_CHESS "○"
-#define HINT_CHESS "#"
-#define NONE 0
-#define HINT 1
-#define BLACK 2
-#define WHITE 3
-
-#define INVERT(COLOR) (((COLOR))==WHITE?BLACK:WHITE)
-
-struct OthelloData {
- char nowx, nowy;
- char number[2];
-
- char pass;
- char if_hint;
- int think, which_table;
-
- char nowboard[10][10];
- char evaltable[NR_TABLE + 1][10][10];
-};
-
-static const char *CHESS_TYPE[] = {NONE_CHESS, HINT_CHESS, BLACK_CHESS, WHITE_CHESS};
-static const char DIRX[] = {-1, -1, -1, 0, 1, 1, 1, 0};
-static const char DIRY[] = {-1, 0, 1, 1, 1, 0, -1, -1};
-static const 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 void
-print_chess(struct OthelloData *od, int x, int y, char chess)
-{
- move(STARTX - 1 + x * 2, STARTY - 2 + y * 4);
- if (chess != HINT || od->if_hint == 1)
- outs(CHESS_TYPE[(int)chess]);
- else
- outs(CHESS_TYPE[NONE]);
- refresh();
-}
-
-static void
-printboard(struct OthelloData *od)
-{
- int i;
-
- move(STARTX, STARTY);
- outs("┌─┬─┬─┬─┬─┬─┬─┬─┐");
- for (i = 0; i < 7; i++) {
- move(STARTX + 1 + i * 2, STARTY);
- outs("│ │ │ │ │ │ │ │ │");
- move(STARTX + 2 + i * 2, STARTY);
- outs("├─┼─┼─┼─┼─┼─┼─┼─┤");
- }
- move(STARTX + 1 + i * 2, STARTY);
- outs("│ │ │ │ │ │ │ │ │");
- move(STARTX + 2 + i * 2, STARTY);
- outs("└─┴─┴─┴─┴─┴─┴─┴─┘");
- print_chess(od, 4, 4, WHITE);
- print_chess(od, 5, 5, WHITE);
- print_chess(od, 4, 5, BLACK);
- print_chess(od, 5, 4, BLACK);
- move(3, 56);
- prints("(黑)%s", cuser.userid);
- move(3, 72);
- outs(": 02");
- move(4, 56);
- outs("(白)電腦 : 02");
- move(6, 56);
- outs("# 可以下之處");
- move(7, 56);
- outs("[q] 退出");
- move(8, 56);
- outs("[h] 開啟/關閉 提示");
- move(9, 56);
- outs("[Enter][Space] 下棋");
- move(10, 56);
- outs("上:↑, i");
- move(11, 56);
- outs("下:↓, k");
- move(12, 56);
- outs("左:←, j");
- move(13, 56);
- outs("右:→, l");
-}
-
-static int
-get_key(struct OthelloData *od, int x, int y)
-{
- int ch;
-
- move(STARTX - 1 + x * 2, STARTY - 1 + y * 4);
- ch = igetch();
- move(STARTX - 1 + x * 2, STARTY - 2 + y * 4);
- if (od->nowboard[x][y] != HINT || od->if_hint == 1)
- outs(CHESS_TYPE[(int)od->nowboard[x][y]]);
- 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;
-
- tmpx = i + DIRX[dir];
- tmpy = j + DIRY[dir];
- tmpchess = chessboard[tmpx][tmpy];
- if (tmpchess == -1)
- return false;
- if (tmpchess != INVERT(color))
- return false;
-
- tmpx += DIRX[dir];
- tmpy += DIRY[dir];
- tmpchess = chessboard[tmpx][tmpy];
- while (tmpchess != -1) {
- if (tmpchess < BLACK)
- return false;
- if (tmpchess == color) {
- while (i != tmpx || j != tmpy) {
- chessboard[i][j] = color;
- i += DIRX[dir];
- j += DIRY[dir];
- }
- return true;
- }
- tmpx += DIRX[dir];
- tmpy += DIRY[dir];
- tmpchess = chessboard[tmpx][tmpy];
- }
- 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++) {
- checkx = x + DIRX[i];
- checky = y + DIRY[i];
- temp = chessboard[checkx][checky];
- if (temp < BLACK)
- continue;
- 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(struct OthelloData *od, char color)
-{
- int i, j, temp = 0;
-
- for (i = 1; i <= 8; i++)
- for (j = 1; j <= 8; j++) {
- if (od->nowboard[i][j] == HINT)
- od->nowboard[i][j] = NONE;
- if (if_can_put(i, j, color, od->nowboard)) {
- od->nowboard[i][j] = HINT;
- temp++;
- }
- print_chess(od, i, j, od->nowboard[i][j]);
- }
- return temp;
-}
-
-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(struct OthelloData *od, int quit)
-{
- FILE *fp;
- char *opponent[] = {"", "CD-65", "", "嬰兒", "小孩", "", "大人", "專家"};
-
- move(STARTX - 1, 30);
- outs(" ");
- move(22, 35);
- fp = fopen(LOGFILE, "a");
- if (quit) {
- if (od->number[0] == 2 && od->number[1] == 2) {
- if (fp)
- fclose(fp);
- return;
- }
- fprintf(fp, "在%s級中, %s臨陣脫逃\n", opponent[od->think], cuser.userid);
- if (fp)
- fclose(fp);
- return;
- }
- if (od->number[0] > od->number[1]) {
- prints("你贏了電腦%02d子", od->number[0] - od->number[1]);
- if (od->think == 6 && od->number[0] - od->number[1] >= 50)
- demoney(200);
- if (od->think == 7 && od->number[0] - od->number[1] >= 40)
- demoney(200);
- if (fp)
- fprintf(fp, "在%s級中, %s以 %02d:%02d 贏了電腦%02d子\n",
- opponent[od->think], cuser.userid, od->number[0], od->number[1],
- od->number[0] - od->number[1]);
- } else if (od->number[1] > od->number[0]) {
- prints("電腦贏了你%02d子", od->number[1] - od->number[0]);
- if (fp) {
- fprintf(fp, "在%s級中, ", opponent[od->think]);
- if (od->number[1] - od->number[0] > 20)
- fprintf(fp, "電腦以 %02d:%02d 慘電%s %02d子\n", od->number[1],
- od->number[0], cuser.userid, od->number[1] - od->number[0]);
- else
- fprintf(fp, "電腦以 %02d:%02d 贏了%s %02d子\n", od->number[1],
- od->number[0], cuser.userid, od->number[1] - od->number[0]);
- }
- } else {
- outs("你和電腦打成平手!!");
- if (fp)
- fprintf(fp, "在%s級中, %s和電腦以 %02d:%02d 打成了平手\n",
- opponent[od->think], cuser.userid, od->number[1], od->number[0]);
- }
- if (fp)
- fclose(fp);
- move(1, 1);
- igetch();
-}
-
-static void
-othello_redraw(struct OthelloData *od)
-{
- int i, j;
-
- for (i = 1; i <= 8; i++)
- for (j = 1; j <= 8; j++)
- print_chess(od, i, j, od->nowboard[i][j]);
-}
-
-static int
-player(struct OthelloData *od, char color)
-{
- int ch;
-
- if (get_hint(od, color)) {
- while (true) {
- ch = get_key(od, od->nowx, od->nowy);
- switch (ch) {
- case 'J':
- case 'j':
- case KEY_LEFT:
- od->nowy--;
- break;
- case 'L':
- case 'l':
- case KEY_RIGHT:
- od->nowy++;
- break;
- case 'I':
- case 'i':
- case KEY_UP:
- od->nowx--;
- break;
- case 'K':
- case 'k':
- case KEY_DOWN:
- od->nowx++;
- break;
- case ' ':
- case KEY_ENTER:
- if (od->nowboard[(int)od->nowx][(int)od->nowy] != HINT)
- break;
- od->pass = 0;
- od->nowboard[(int)od->nowx][(int)od->nowy] = color;
- eat(od->nowx, od->nowy, color, od->nowboard);
- print_chess(od, od->nowx, od->nowy, color);
- return true;
- case 'q':
- end_of_game(od, 1);
- return false;
- case 'H':
- case 'h':
- od->if_hint = od->if_hint ^ 1;
- othello_redraw(od);
- break;
- }
- if (od->nowx == 9)
- od->nowx = 1;
- if (od->nowx == 0)
- od->nowx = 8;
- if (od->nowy == 9)
- od->nowy = 1;
- if (od->nowy == 0)
- od->nowy = 8;
- }
- } else {
- od->pass++;
- if (od->pass == 1) {
- move(23, 34);
- outs("你必需放棄這一步!!");
- igetch();
- move(28, 23);
- outs(" ");
- } else {
- end_of_game(od,0);
- return false;
- }
- }
- return 0;
-}
-
-static void
-init(struct OthelloData *od)
-{
- int i, j, i1, j1;
-
- memset(od, 0, sizeof(struct OthelloData));
- od->nowx = 4;
- od->nowy = 4;
- od->number[0] = od->number[1] = 2;
- 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);
- od->evaltable[0][i][j] = init_table[0][i1][j1];
- od->evaltable[1][i][j] = init_table[1][i1][j1];
- }
- memset(od->nowboard, NONE, sizeof(od->nowboard));
- for(i=0;i<10;i++)
- od->nowboard[i][0]=od->nowboard[0][i]=od->nowboard[i][9]=od->nowboard[9][i]=-1;
- od->nowboard[4][4] = od->nowboard[5][5] = WHITE;
- od->nowboard[4][5] = od->nowboard[5][4] = BLACK;
-}
-
-static void
-report(struct OthelloData *od)
-{
- int i, j;
-
- od->number[0] = od->number[1] = 0;
- for (i = 1; i <= 8; i++)
- for (j = 1; j <= 8; j++)
- if (od->nowboard[i][j] == BLACK)
- od->number[0]++;
- else if (od->nowboard[i][j] == WHITE)
- od->number[1]++;
- move(3, 60);
- outs(cuser.userid);
- move(3, 72);
- prints(": %02d", od->number[0]);
- move(4, 60);
- prints("電腦 : %02d", od->number[1]);
-}
-
-static int
-EVL(struct OthelloData *od, 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 += od->evaltable[table_number][a][b];
- else
- points -= od->evaltable[table_number][a][b];
- }
- return ((color == BLACK) ? points : -points);
-}
-
-static int
-alphabeta(struct OthelloData *od, 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(od, 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)) {
- flag = 0;
- memcpy(tempboard, chessboard, sizeof(char) * 100);
- eat(i, j, color, tempboard);
-
- k = alphabeta(od, alpha, beta, level + 1, tempboard, thinkstep,
- ((color - 2) ^ 1) + 2, table);
- if (((level & 1) && k > alpha))
- alpha = k;
- else if (!(level & 1) && k < beta)
- beta = k;
- if (alpha >= beta)
- break;
- }
- }
- }
- if (flag)
- return EVL(od, chessboard, color, table);
- return ((level & 1) ? alpha : beta);
-}
-
-static int
-Computer(struct OthelloData *od, int thinkstep, int table)
-{
- int i, j, maxi = 0, maxj = 0, level = 1;
- char chessboard[10][10];
- int alpha = -10000, k;
- if ((od->number[0] + od->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, od->nowboard)) {
- memcpy(chessboard, od->nowboard, sizeof(char) * 100);
- eat(i, j, WHITE, chessboard);
- k = alphabeta(od, alpha, 10000, level + 1, chessboard, thinkstep,
- BLACK, table);
- if (k > alpha) {
- alpha = k;
- maxi = i;
- maxj = j;
- }
- }
- }
- if (alpha != -10000) {
- eat(maxi, maxj, WHITE, od->nowboard);
- od->pass = 0;
- od->nowx = maxi;
- od->nowy = maxj;
- } else {
- move(23, 30);
- outs("電腦放棄這一步棋!!");
- od->pass++;
- if (od->pass == 2) {
- move(23, 24);
- outs(" ");
- end_of_game(od, 0);
- return false;
- }
- igetch();
- move(23, 24);
- outs(" ");
- }
- return true;
-}
-
-static int
-choose(void)
-{
- char thinkstep[2];
-
- move(2, 0);
- outs("請選擇難度:");
- move(5, 0);
- outs("[0] 離開\n");
- outs("(1) CD-65\n");/* 想 1 步 */
- outs("(2) 嬰兒\n"); /* 想 3 步 */
- outs("(3) 小孩\n"); /* 想 4 步 */
- do {
- if (getdata(4, 0, "請選擇一個對象和您對打:(1~3)",
- thinkstep, sizeof(thinkstep), LCECHO) == 0 ||
- thinkstep[0] == '0')
- return 0;
-
- } while (thinkstep[0] < '1' || thinkstep[0] > '3');
- clear();
- switch (thinkstep[0]) {
- case '2':
- thinkstep[0] = '3';
- break;
- case '3':
- thinkstep[0] = '4';
- break;
- default:
- thinkstep[0] = '1';
- break;
- }
- return atoi(thinkstep);
-}
-
-#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0
-
-int
-othello_main(void)
-{
- struct OthelloData *od;
-
- lockreturn0(OTHELLO, LOCK_MULTI);
-
- od=(struct OthelloData*)malloc(sizeof(struct OthelloData));
- if(od==NULL) {
- unlockutmpmode();
- return 0;
- }
-
- clear();
- init(od);
- od->think = choose();
- if (!od->think)
- {
- unlockutmpmode();
- free(od);
- return 0;
- }
- showtitle("單人黑白棋", BBSName);
- printboard(od);
- od->which_table = random() % NR_TABLE;
- while (true) {
- move(STARTX - 1, 30);
- outs("輪到你下了...");
- if (!player(od, BLACK))
- break;
- report(od);
- othello_redraw(od);
- if (od->number[0] + od->number[1] == 64) {
- end_of_game(od, 0);
- break;
- }
- move(STARTX - 1, 30);
- outs("電腦思考中...");
- refresh();
- if (!Computer(od, od->think, od->which_table))
- break;
- report(od);
- othello_redraw(od);
- if (od->number[0] + od->number[1] == 64) {
- end_of_game(od, 0);
- break;
- }
- }
- more(LOGFILE, YEA);
- unlockutmpmode();
- free(od);
- return 1;
-}