/* $Id$ */
#include "bbs.h"
typedef int (*play_func_t) (int, chcusr_t *, chcusr_t *, board_t, board_t);
static int chc_ipass = 0, chc_hepass = 0;
#define CHC_TIMEOUT 300
#define SIDE_ROW 10
#define TURN_ROW 11
#define STEP_ROW 12
#define TIME_ROW 13
#define WARN_ROW 15
#define MYWIN_ROW 17
#define HISWIN_ROW 18
static void
chcusr_put(userec_t *userec, chcusr_t *user)
{
userec->chc_win = user->win;
userec->chc_lose = user->lose;
userec->chc_tie = user->tie;
}
static void
chcusr_get(userec_t *userec, chcusr_t *user)
{
strlcpy(user->userid, userec->userid, sizeof(user->userid));
user->win = userec->chc_win;
user->lose = userec->chc_lose;
user->tie = userec->chc_tie;
}
static int
hisplay(int s, chcusr_t *user1, chcusr_t *user2, board_t board, board_t tmpbrd)
{
int start_time;
int endgame = 0, endturn = 0;
start_time = now;
while (!endturn) {
chc_lefttime = CHC_TIMEOUT - (now - start_time);
if (chc_lefttime < 0) {
chc_lefttime = 0;
/* to make him break out igetkey() */
chc_from.r = -2;
chc_sendmove(s);
}
chc_drawline(board, user1, user2, TIME_ROW);
move(1, 0);
oflush();
switch (igetkey()) {
case 'q':
endgame = 2;
endturn = 1;
break;
case 'p':
if (chc_hepass) {
chc_from.r = -1;
chc_sendmove(s);
endgame = 3;
endturn = 1;
}
break;
case I_OTHERDATA:
if (chc_recvmove(s)) { /* disconnect */
endturn = 1;
endgame = 1;
} else {
if (chc_from.r == -1) {
chc_hepass = 1;
strlcpy(chc_warnmsg, "\033[1;33m要求和局!\033[m", sizeof(chc_warnmsg));
chc_drawline(board, user1, user2, WARN_ROW);
} else {
chc_from.r = 9 - chc_from.r, chc_from.c = 8 - chc_from.c;
chc_to.r = 9 - chc_to.r, chc_to.c = 8 - chc_to.c;
chc_cursor = chc_to;
if (CHE_P(board[chc_to.r][chc_to.c]) == 1)
endgame = 2;
endturn = 1;
chc_hepass = 0;
chc_drawline(board, user1, user2, STEP_ROW);
chc_movechess(board);
chc_drawline(board, user1, user2, LTR(chc_from.r));
chc_drawline(board, user1, user2, LTR(chc_to.r));
}
}
break;
}
}
return endgame;
}
static int
myplay(int s, chcusr_t *user1, chcusr_t *user2, board_t board, board_t tmpbrd)
{
int ch, start_time;
int endgame = 0, endturn = 0;
chc_ipass = 0, chc_selected = 0;
start_time = now;
chc_lefttime = CHC_TIMEOUT - (now - start_time);
bell();
while (!endturn) {
chc_drawline(board, user1, user2, TIME_ROW);
chc_movecur(chc_cursor.r, chc_cursor.c);
oflush();
ch = igetkey();
chc_lefttime = CHC_TIMEOUT - (now - start_time);
if (chc_lefttime < 0)
ch = 'q';
switch (ch) {
case I_OTHERDATA:
if (chc_recvmove(s)) { /* disconnect */
endgame = 1;
endturn = 1;
} else if (chc_from.r == -1 && chc_ipass) {
endgame = 3;
endturn = 1;
}
break;
case KEY_UP:
chc_cursor.r--;
if (chc_cursor.r < 0)
chc_cursor.r = BRD_ROW - 1;
break;
case KEY_DOWN:
chc_cursor.r++;
if (chc_cursor.r >= BRD_ROW)
chc_cursor.r = 0;
break;
case KEY_LEFT:
chc_cursor.c--;
if (chc_cursor.c < 0)
chc_cursor.c = BRD_COL - 1;
break;
case KEY_RIGHT:
chc_cursor.c++;
if (chc_cursor.c >= BRD_COL)
chc_cursor.c = 0;
break;
case 'q':
endgame = 2;
endturn = 1;
break;
case 'p':
chc_ipass = 1;
chc_from.r = -1;
chc_sendmove(s);
strlcpy(chc_warnmsg, "\033[1;33m要求和棋!\033[m", sizeof(chc_warnmsg));
chc_drawline(board, user1, user2, WARN_ROW);
bell();
break;
case '\r':
case '\n':
case ' ':
if (chc_selected) {
if (chc_cursor.r == chc_select.r &&
chc_cursor.c == chc_select.c) {
chc_selected = 0;
chc_drawline(board, user1, user2, LTR(chc_cursor.r));
} else if (chc_canmove(board, chc_select, chc_cursor)) {
if (CHE_P(board[chc_cursor.r][chc_cursor.c]) == 1)
endgame = 1;
chc_from = chc_select;
chc_to = chc_cursor;
if (!endgame) {
memcpy(tmpbrd, board, sizeof(board_t));
chc_movechess(tmpbrd);
}
if (endgame || !chc_iskfk(tmpbrd)) {
chc_drawline(board, user1, user2, STEP_ROW);
chc_movechess(board);
chc_sendmove(s);
chc_selected = 0;
chc_drawline(board, user1, user2, LTR(chc_from.r));
chc_drawline(board, user1, user2, LTR(chc_to.r));
endturn = 1;
} else {
strlcpy(chc_warnmsg, "\033[1;33m不可以王見王\033[m", sizeof(chc_warnmsg));
bell();
chc_drawline(board, user1, user2, WARN_ROW);
}
}
} else if (board[chc_cursor.r][chc_cursor.c] &&
CHE_O(board[chc_cursor.r][chc_cursor.c]) == chc_turn) {
chc_selected = 1;
chc_select = chc_cursor;
chc_drawline(board, user1, user2, LTR(chc_cursor.r));
}
break;
}
}
return endgame;
}
static void
mainloop(int s, chcusr_t *user1, chcusr_t *user2, board_t board, play_func_t play_func[2])
{
int endgame;
board_t tmpbrd;
play_func[chc_my] = myplay;
if(s != 0)
play_func[chc_my ^ 1] = hisplay;
else /* 跟自己下棋 */
play_func[chc_my ^ 1] = myplay;
for (chc_turn = 1, endgame = 0; !endgame; chc_turn ^= 1) {
chc_firststep = 0;
chc_drawline(board, user1, user2, TURN_ROW);
if (chc_ischeck(board, chc_turn)) {
strlcpy(chc_warnmsg, "\033[1;31m將軍!\033[m", sizeof(chc_warnmsg));
bell();
} else
chc_warnmsg[0] = 0;
chc_drawline(board, user1, user2, WARN_ROW);
endgame = play_func[chc_turn] (s, user1, user2, board, tmpbrd);
}
if (s != 0) {
if (endgame == 1) {
strlcpy(chc_warnmsg, "對方認輸了!", sizeof(chc_warnmsg));
user1->win++;
currutmp->chc_win++;
} else if (endgame == 2) {
strlcpy(chc_warnmsg, "你認輸了!", sizeof(chc_warnmsg));
user1->lose++;
currutmp->chc_lose++;
} else {
strlcpy(chc_warnmsg, "和棋", sizeof(chc_warnmsg));
user1->tie++;
currutmp->chc_tie++;
}
}
else {
strlcpy(chc_warnmsg, "結束打譜", sizeof(chc_warnmsg));
}
user1->lose--;
// if not watching
chcusr_put(&cuser, user1);
passwd_update(usernum, &cuser);
chc_drawline(board, user1, user2, WARN_ROW);
bell();
oflush();
}
static void
chc_init(int s, chcusr_t *user1, chcusr_t *user2, board_t board)
{
userinfo_t *my = currutmp;
setutmpmode(CHC);
clear();
chc_warnmsg[0] = 0;
if(s != 0){ // XXX mateid -> user2
chc_my = my->turn;
chc_mateid = my->mateid;
}
else{
chc_my = 1;
chc_mateid = cuser.userid;
}
chc_firststep = 1;
chc_init_board(board);
chc_redraw(user1, user2, board);
chc_cursor.r = 9, chc_cursor.c = 0;
add_io(s, 0);
if (my->turn)
chc_recvmove(s);
user1->lose++;
// if not watching
passwd_query(usernum, &xuser);
chcusr_put(&xuser, user1);
passwd_update(usernum, &xuser);
if (!my->turn) {
chc_sendmove(s);
user2->lose++;
}
chc_redraw(user1, user2, board);
}
static void
chc_userinit(char *userid1, char *userid2, chcusr_t *user1, chcusr_t *user2, play_func_t play_func[2])
{
getuser(userid1);
chcusr_get(&xuser, user1);
getuser(userid2);
chcusr_get(&xuser, user2);
}
void
chc(int s, int type)
{
board_t board;
chcusr_t user1, user2;
play_func_t play_func[2];
chc_userinit(cuser.userid, currutmp->mateid, &user1, &user2, play_func);
chc_init(s, &user1, &user2, board);
mainloop(s, &user1, &user2, board, play_func);
if (type == CHC_VERSUS)
close(s);
add_io(0, 0);
if (chc_my)
pressanykey();
}