From 2bc657336cf51255ea6d0bf47c1792347d4bf8d3 Mon Sep 17 00:00:00 2001 From: scw Date: Sat, 24 Mar 2007 08:51:42 +0000 Subject: Set timeout for confirmation when playing chess to avoid wasting others' time. git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@3491 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- mbbsd/chess.c | 57 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 18 deletions(-) (limited to 'mbbsd') diff --git a/mbbsd/chess.c b/mbbsd/chess.c index 04344d80..264b8553 100644 --- a/mbbsd/chess.c +++ b/mbbsd/chess.c @@ -1,6 +1,7 @@ /* $Id$ */ #include "bbs.h" #include "chess.h" +#include #define assert_not_reached() assert(!"Should never be here!!!") #define dim(x) (sizeof(x) / sizeof(x[0])) @@ -25,6 +26,21 @@ #define CONNECT_PEER() add_io(info->sock, 0) #define IGNORE_PEER() add_io(0, 0) +#define DO_WITHOUT_PEER(TIMEOUT,ACT,ELSE) \ + do { \ + void (*orig_alarm_handler)(int) = \ + Signal(SIGALRM, &SigjmpEnv); \ + IGNORE_PEER(); \ + if(sigsetjmp(sigjmpEnv, 1)) \ + ELSE; \ + else { \ + alarm(TIMEOUT); \ + ACT; \ + } \ + CONNECT_PEER(); \ + Signal(SIGALRM, orig_alarm_handler); \ + } while(0) + static const char * const ChessHintStr[] = { " q 認輸離開", " p 要求和棋", @@ -44,12 +60,15 @@ static const struct { }; static ChessInfo * CurrentPlayingGameInfo; +static sigjmp_buf sigjmpEnv; /* XXX: This is a BAD way to pass information. * Fix this by handling chess request ourselves. */ static ChessTimeLimit * _current_time_limit; +static void SigjmpEnv(int sig) { siglongjmp(sigjmpEnv, 1); } + #define CHESS_HISTORY_ENTRY(INFO,N) \ ((INFO)->history.body + (N) * (INFO)->constants->step_entry_size) static void @@ -385,9 +404,9 @@ ChessAnswerRequest(ChessInfo* info, const char* req_name) snprintf(msg, sizeof(msg), "對方要求%s,是否接受?(y/N)", req_name); - IGNORE_PEER(); - getdata(b_lines, 0, msg, buf, sizeof(buf), DOECHO); - CONNECT_PEER(); + DO_WITHOUT_PEER(30, + getdata(b_lines, 0, msg, buf, sizeof(buf), DOECHO), + buf[0] = 'n'); ChessDrawHelpLine(info); info->warnmsg[0] = 0; @@ -514,13 +533,14 @@ ChessPlayFuncMy(ChessInfo* info) case 'q': { char buf[4]; - IGNORE_PEER(); + + DO_WITHOUT_PEER(30, getdata(b_lines, 0, info->mode == CHESS_MODE_PERSONAL ? "是否真的要離開?(y/N)" : "是否真的要認輸?(y/N)", - buf, sizeof(buf), DOECHO); - CONNECT_PEER(); + buf, sizeof(buf), DOECHO), + buf[0] = 'n'); ChessDrawHelpLine(info); if (buf[0] == 'y' || buf[0] == 'Y') { @@ -541,10 +561,11 @@ ChessPlayFuncMy(ChessInfo* info) endturn = 1; } else if (info->mode != CHESS_MODE_PERSONAL) { char buf[4]; - IGNORE_PEER(); + + DO_WITHOUT_PEER(30, getdata(b_lines, 0, "是否真的要和棋?(y/N)", - buf, sizeof(buf), DOECHO); - CONNECT_PEER(); + buf, sizeof(buf), DOECHO), + buf[0] = 'n'); ChessDrawHelpLine(info); if (buf[0] == 'y' || buf[1] == 'Y') { @@ -584,10 +605,10 @@ ChessPlayFuncMy(ChessInfo* info) default: if (info->actions->process_key) { - IGNORE_PEER(); + DO_WITHOUT_PEER(30, endturn = - info->actions->process_key(info, ch, &game_result); - CONNECT_PEER(); + info->actions->process_key(info, ch, &game_result), + ); } } } @@ -625,10 +646,10 @@ ChessPlayFuncHis(ChessInfo* info) case 'q': { char buf[4]; - IGNORE_PEER(); + DO_WITHOUT_PEER(30, getdata(b_lines, 0, "是否真的要認輸?(y/N)", - buf, sizeof(buf), DOECHO); - CONNECT_PEER(); + buf, sizeof(buf), DOECHO), + buf[0] = 'n'); ChessDrawHelpLine(info); if (buf[0] == 'y' || buf[0] == 'Y') { @@ -708,10 +729,10 @@ ChessPlayFuncHis(ChessInfo* info) default: if (info->actions->process_key) { - IGNORE_PEER(); + DO_WITHOUT_PEER(30, endturn = - info->actions->process_key(info, ch, &game_result); - CONNECT_PEER(); + info->actions->process_key(info, ch, &game_result), + ); } } } -- cgit v1.2.3