/* $Id$ */
#include "bbs.h"
#define RED 1
#define BLACK 0
typedef short int sint;
typedef struct item {
short int color, value, die, out;
} item;
typedef struct cur {
short int y, x, end;
} cur;
struct DarkData {
item brd[4][8];
cur curr;
sint rcount, bcount, cont, fix; /* cont:是否可連吃 */
sint my, mx, mly, mlx; /* 移動的座標 標 */
sint cur_eaty, cur_eatx; /* 吃掉對方其子的秀出座標 */
};
static char * const rname[] = {"兵", "炮", "傌", "車", "相", "仕", "帥"};
static char * const bname[] = {"卒", "包", "馬", "車", "象", "士", "將"};
static const sint cury[] = {3, 5, 7, 9}, curx[] = {5, 9, 13, 17, 21, 25, 29, 33};
static void
brdswap(struct DarkData *dd, sint y, sint x, sint ly, sint lx)
{
memcpy(&dd->brd[y][x], &dd->brd[ly][lx], sizeof(item));
dd->brd[ly][lx].die = 1;
dd->brd[ly][lx].color = -1; /* 沒這個color */
dd->brd[ly][lx].value = -1;
}
static sint
Is_win(struct DarkData *dd, item att, item det, sint y, sint x, sint ly, sint lx)
{
sint i, c = 0, min, max;
if (att.value == 1) { /* 砲 */
if (y != ly && x != lx)
return 0;
if ((abs(ly - y) == 1 && dd->brd[y][x].die == 0) ||
(abs(lx - x) == 1 && dd->brd[y][x].die == 0))
return 0;
if (y == ly) {
if (x > lx) {
max = x;
min = lx;
} else {
max = lx;
min = x;
}
for (i = min + 1; i < max; i++)
if (dd->brd[y][i].die == 0)
c++;
} else if (x == lx) {
if (y > ly) {
max = y;
min = ly;
} else {
max = ly;
min = y;
}
for (i = min + 1; i < max; i++)
if (dd->brd[i][x].die == 0)
c++;
}
if (c != 1)
return 0;
if (det.die == 1)
return 0;
return 1;
}
/* 非砲 */
if (((abs(ly - y) == 1 && x == lx) || (abs(lx - x) == 1 && ly == y)) && dd->brd[y][x].out == 1) {
if (att.value == 0 && det.value == 6)
return 1;
else if (att.value == 6 && det.value == 0)
return 0;
else if (att.value >= det.value)
return 1;
else
return 0;
}
return 0;
}
static sint
Is_move(struct DarkData *dd, sint y, sint x, sint ly, sint lx)
{
if (dd->brd[y][x].die == 1 && ((abs(ly - y) == 1 && x == lx) || (abs(lx - x) == 1 && ly == y)))
return 1;
return 0;
}
static void
brd_rand(struct DarkData *dd)
{
sint y, x, index;
sint tem[32];
sint value[32] = {
0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6
};
bzero(dd->brd, sizeof(dd->brd));
bzero(tem, sizeof(tem));
bzero(&dd->curr, sizeof(dd->curr));
for (y = 0; y < 4; y++)
for (x = 0; x < 8; x++)
while (1) {
index = random() % 32;
if (tem[index])
continue;
dd->brd[y][x].color = (index > 15) ? 0 : 1;
dd->brd[y][x].value = value[index];
tem[index] = 1;
break;
}
}
static void
brd_prints(void)
{
clear();
move(1, 0);
outs("\n"
" " ANSI_COLOR(43;30) "╭─┬─┬─┬─┬─┬─┬─┬─╮" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "│●│●│●│●│●│●│●│●│" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "├─┼─┼─┼─┼─┼─┼─┼─┤" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "│●│●│●│●│●│●│●│●│" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "├─┼─┼─┼─┼─┼─┼─┼─┤" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "│●│●│●│●│●│●│●│●│" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "├─┼─┼─┼─┼─┼─┼─┼─┤" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "│●│●│●│●│●│●│●│●│" ANSI_RESET "\n"
" " ANSI_COLOR(43;30) "╰─┴─┴─┴─┴─┴─┴─┴─╯" ANSI_RESET "\n"
" ");
}
static void
draw_line(struct DarkData *dd, sint y, sint f)
{
sint i;
char buf[1024], tmp[256];
*buf = 0;
*tmp = 0;
strlcpy(buf, ANSI_COLOR(43;30), sizeof(buf));
for (i = 0; i < 8; i++) {
if (dd->brd[y][i].die == 1)
snprintf(tmp, sizeof(tmp), "│ ");
else if (dd->brd[y][i].out == 0)
snprintf(tmp, sizeof(tmp), "│●");
else {
snprintf(tmp, sizeof(tmp), "│" ANSI_COLOR(%s1;%d) "%s" ANSI_RESET ANSI_COLOR(43;30) "",
(f == i) ? "1;47;" : "", (dd->brd[y][i].color) ? 31 : 34,
(dd->brd[y][i].color) ? rname[dd->brd[y][i].value] :
bname[dd->brd[y][i].value]);
}
strcat(buf, tmp);
}
strcat(buf, "│" ANSI_RESET);
move(cury[y], 3);
clrtoeol();
outs(buf);
}
static void
redraw(struct DarkData *dd)
{
sint i = 0;
for (; i < 4; i++)
draw_line(dd, i, -1);
}
static sint
playing(struct DarkData *dd, sint fd, sint color, sint ch, sint * b, userinfo_t * uin)
{
dd->curr.end = 0;
move(cury[dd->my], curx[dd->mx]);
if (dd->fix) {
if (ch == 's') {
dd->fix = 0;
*b = 0;
return 0;
} else {
draw_line(dd, dd->mly, -1);
}
}
switch (ch) {
case KEY_LEFT:
if (dd->mx == 0)
dd->mx = 7;
else
dd->mx--;
move(cury[dd->my], curx[dd->mx]);
*b = -1;
break;
case KEY_RIGHT:
if (dd->mx == 7)
dd->mx = 0;
else
dd->mx++;
move(cury[dd->my], curx[dd->mx]);
*b = -1;
break;
case KEY_UP:
if (dd->my == 0)
dd->my = 3;
else
dd->my--;
move(cury[dd->my], curx[dd->mx]);
*b = -1;
break;
case KEY_DOWN:
if (dd->my == 3)
dd->my = 0;
else
dd->my++;
move(cury[dd->my], curx[dd->mx]);
*b = -1;
break;
case 'q':
case 'Q':
if (!color)
dd->bcount = 0;
else
dd->rcount = 0;
*b = 0;
return -2;
case 'p':
case 'P':
return -3;
case 'c':
return -4;
case 'g':
return -5;
case 's': /* 翻開棋子 或是選擇棋子 */
/* 選擇棋子 */
if (dd->brd[dd->my][dd->mx].out == 1) {
if (dd->brd[dd->my][dd->mx].color != color) {
*b = -1;
break;
}
if (dd->mly < 0) { /* 可以選擇 */
dd->mly = dd->my;
dd->mlx = dd->mx;
draw_line(dd, dd->my, dd->mx);
*b = -1;
break;
} else if (dd->mly == dd->my && dd->mlx == dd->mx) { /* 不選了 */
dd->mly = -1;
dd->mlx = -1;
draw_line(dd, dd->my, -1);
} else {
draw_line(dd, dd->mly, -1);
dd->mly = dd->my;
dd->mlx = dd->mx;
if (dd->brd[dd->mly][dd->mlx].value == 1)
dd->fix = 1;
draw_line(dd, dd->my, dd->mx);
}
*b = -1;
break;
}
/* 翻開棋子 */
if (dd->mly >= 0) {
*b = -1;
break;
} /* 本來就是翻開的 */
/* 決定一開始的顏色 */
if (currutmp->color == '.') {
if (uin->color != '1' && uin->color != '0')
currutmp->color = (dd->brd[dd->my][dd->mx].color) ? '1' : '0';
else
currutmp->color = (uin->color == '0') ? '1' : '0';
}
dd->brd[dd->my][dd->mx].out = 1;
draw_line(dd, dd->my, -1);
move(cury[dd->my], curx[dd->mx]);
*b = 0;
break;
case 'u':
move(0, 0);
clrtoeol();
prints("%s色%s cont=%d",
(dd->brd[dd->my][dd->mx].color == RED) ? "紅" : "黑",
rname[dd->brd[dd->my][dd->mx].value], dd->cont);
*b = -1;
break;
case '\r': /* 吃 or 移動 ly跟lx必須大於0 */
case '\n':
if (
dd->mly >= 0 /* 要先選子 */
&&
dd->brd[dd->mly][dd->mlx].color != dd->brd[dd->my][dd->mx].color /* 同色不能移動也不能吃 */
&&
(Is_move(dd, dd->my, dd->mx, dd->mly, dd->mlx) ||
Is_win(dd, dd->brd[dd->mly][dd->mlx], dd->brd[dd->my][dd->mx], dd->my, dd->mx, dd->mly, dd->mlx))
) {
if (dd->fix && dd->brd[dd->my][dd->mx].value < 0) {
*b = -1;
return 0;
}
if (dd->brd[dd->my][dd->mx].value >= 0 && dd->brd[dd->my][dd->mx].die == 0) {
if (!color)
dd->bcount--;
else
dd->rcount--;
move(dd->cur_eaty, dd->cur_eatx);
if(color)
outs(bname[dd->brd[dd->my][dd->mx].value]);
else
outs(rname[dd->brd[dd->my][dd->mx].value]);
if (dd->cur_eatx >= 26) {
dd->cur_eatx = 5;
dd->cur_eaty++;
} else
dd->cur_eatx += 3;
}
brdswap(dd, dd->my, dd->mx, dd->mly, dd->mlx);
draw_line(dd, dd->mly, -1);
draw_line(dd, dd->my, -1);
if (dd->fix == 1)
*b = -1;
else {
dd->mly = -1;
dd->mlx = -1;
*b = 0;
}
} else
*b = -1;
break;
default:
*b = -1;
}
if (!dd->rcount)
return -1;
else if (!dd->bcount)
return -1;
if (*b == -1)
return 0;
dd->curr.y = dd->my;
dd->curr.x = dd->mx;
dd->curr.end = (!*b) ? 1 : 0;
send(fd, &dd->curr, sizeof(dd->curr), 0);
send(fd, &dd->brd, sizeof(dd->brd), 0);
return 0;
}
int
main_dark(int fd, userinfo_t * uin)
{
sint end = 0, ch = 1, i = 0;
char buf[16];
struct DarkData dd;
memset(&dd, 0, sizeof(dd));
dd.my=dd.mx=0;
dd.mly=dd.mlx=-1;
*buf = 0;
dd.fix = 0;
currutmp->color = '.';
/* '.' 表示還沒決定顏色 */
dd.rcount = 16;
dd.bcount = 16;
//initialize
dd.cur_eaty = 18, dd.cur_eatx = 5;
setutmpmode(DARK);
brd_prints();
if (currutmp->turn) {
brd_rand(&dd);
send(fd, &dd.brd, sizeof(dd.brd), 0);
mouts(21, 0, " " ANSI_COLOR(1;37) ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;37) "你是先手" ANSI_RESET);
mouts(22, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(5;35) "輪到你下了" ANSI_RESET);
} else {
recv(fd, &dd.brd, sizeof(dd.brd), 0);
mouts(21, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;37) "你是後手" ANSI_RESET);
}
move(12, 3);
prints("%s[0勝0敗]" ANSI_COLOR(5;31) "vs" ANSI_COLOR(1;37) "." ANSI_RESET "%s[0勝0敗]", currutmp->userid, currutmp->mateid);
outs("\n"
" " ANSI_COLOR(1;36) "╳╱" ANSI_COLOR(1;31) "功\能表" ANSI_COLOR(1;36) "╲╳╲╱╳╲" ANSI_RESET "\n"
" " ANSI_COLOR(1;36) "╱" ANSI_COLOR(1;33) " ↑←↓→" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) "移動" ANSI_RESET "\n"
" " ANSI_COLOR(1;36) "╳" ANSI_COLOR(1;33) " s" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " 選子,翻子" ANSI_RESET "\n"
" " ANSI_COLOR(1;36) "╱" ANSI_COLOR(1;33) " enter" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " 吃棋,放棋" ANSI_RESET "\n"
" " ANSI_COLOR(1;33) "已經解決的" ANSI_COLOR(1;37) ":" ANSI_COLOR(1;36) " ╳" ANSI_COLOR(1;33) " p" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " 合棋" ANSI_RESET "\n"
" " ANSI_COLOR(1;36) "╱" ANSI_COLOR(1;33) " q" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " 認輸" ANSI_RESET "\n"
" " ANSI_COLOR(1;36) "╳" ANSI_COLOR(1;33) " c" ANSI_COLOR(1;37) ": " ANSI_COLOR(1;35) " 換邊" ANSI_RESET);
if (currutmp->turn)
move(cury[0], curx[0]);
add_io(fd, 0);
while (end <= 0) {
if (uin->turn == 'w' || currutmp->turn == 'w') {
end = -1;
break;
}
ch = igetch();
if (ch == I_OTHERDATA) {
ch = recv(fd, &dd.curr, sizeof(dd.curr), 0);
if (ch != sizeof(dd.curr)) {
if (uin->turn == 'e') {
end = -3;
break;
} else if (uin->turn != 'w') {
end = -1;
currutmp->turn = 'w';
break;
}
end = -1;
break;
}
if (dd.curr.end == -3)
mouts(23, 30, ANSI_COLOR(33) "要求合棋" ANSI_RESET);
else if (dd.curr.end == -4)
mouts(23, 30, ANSI_COLOR(33) "要求換邊" ANSI_RESET);
else if (dd.curr.end == -5)
mouts(23, 30, ANSI_COLOR(33) "要求連吃" ANSI_RESET);
else
mouts(23, 30, "");
recv(fd, &dd.brd, sizeof(dd.brd), 0);
dd.my = dd.curr.y;
dd.mx = dd.curr.x;
redraw(&dd);
if (dd.curr.end)
mouts(22, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(5;35) "輪到你下了" ANSI_RESET);
move(cury[dd.my], curx[dd.mx]);
} else {
if (currutmp->turn == 'p') {
if (ch == 'y') {
end = -3;
currutmp->turn = 'e';
break;
} else {
mouts(23, 30, "");
*buf = 0;
currutmp->turn = (uin->turn) ? 0 : 1;
}
} else if (currutmp->turn == 'c') {
if (ch == 'y') {
currutmp->color = (currutmp->color == '1') ? '0' : '1';
uin->color = (uin->color == '1') ? '0' : '1';
mouts(21, 0, (currutmp->color == '1') ? " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;31) "你持紅色棋" ANSI_RESET : " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;36) "你持黑色棋" ANSI_RESET);
} else {
mouts(23, 30, "");
currutmp->turn = (uin->turn) ? 0 : 1;
}
} else if (currutmp->turn == 'g') {
if (ch == 'y') {
dd.cont = 1;
mouts(21, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;31) "你持紅色棋" ANSI_RESET " 可連吃");
} else {
mouts(23, 30, "");
currutmp->turn = (uin->turn) ? 0 : 1;
}
}
if (currutmp->turn == 1) {
sint go_on = 0;
if (uin->turn == 'g') {
dd.cont = 1;
uin->turn = (currutmp->turn) ? 0 : 1;
mouts(21, 10, "可連吃");
}
end = playing(&dd, fd, currutmp->color - '0', ch, &go_on, uin);
if (end == -1) {
currutmp->turn = 'w';
break;
} else if (end == -2) {
uin->turn = 'w';
break;
} else if (end == -3) {
uin->turn = 'p';
dd.curr.end = -3;
send(fd, &dd.curr, sizeof(dd.curr), 0);
send(fd, &dd.brd, sizeof(buf), 0);
continue;
} else if (end == -4) {
if (currutmp->color != '1' && currutmp->color != '0')
continue;
uin->turn = 'c';
i = 0;
dd.curr.end = -4;
send(fd, &dd.curr, sizeof(dd.curr), 0);
send(fd, &dd.brd, sizeof(buf), 0);
continue;
} else if (end == -5) {
uin->turn = 'g';
dd.curr.end = -5;
send(fd, &dd.curr, sizeof(dd.curr), 0);
send(fd, &dd.brd, sizeof(buf), 0);
continue;
}
if (!i && currutmp->color == '1') {
mouts(21, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;31) "你持紅色棋" ANSI_RESET);
i++;
move(cury[dd.my], curx[dd.mx]);
}
if (!i && currutmp->color == '0') {
mouts(21, 0, " " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;36) "你持黑色棋" ANSI_RESET);
i++;
move(cury[dd.my], curx[dd.mx]);
}
if (uin->turn == 'e') {
end = -3;
break;
}
if (go_on < 0)
continue;
move(22, 0);
clrtoeol();
prints(" " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;37) "輪到%s下 別怕別怕 他算啥米" ANSI_RESET, currutmp->mateid);
currutmp->turn = 0;
uin->turn = 1;
} else {
if (ch == 'q') {
uin->turn = 'w';
break;
}
move(22, 0);
clrtoeol();
prints(" " ANSI_COLOR(1;33) "◆" ANSI_COLOR(1;37) "輪到%s下 別怕別怕 他算啥米" ANSI_RESET, currutmp->mateid);
}
}
}
switch (end) {
case -1:
case -2:
if (currutmp->turn == 'w') {
move(22, 0);
clrtoeol();
outs(ANSI_COLOR(1;31) "你贏了.. 真是恭喜~~" ANSI_RESET);
} else {
move(22, 0);
clrtoeol();
outs(ANSI_COLOR(1;31) "輸掉了啦.....下次讓他好看!!" ANSI_RESET);
}
break;
case -3:
mouts(22, 0, ANSI_COLOR(1;31) "合棋唷!! 下次在分高下吧 ^_^" ANSI_RESET);
break;
default:
add_io(0, 0);
close(fd);
pressanykey();
return 0;
}
add_io(0, 0);
close(fd);
pressanykey();
return 0;
}