summaryrefslogtreecommitdiffstats
path: root/mbbsd/gomo.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbbsd/gomo.c')
-rw-r--r--mbbsd/gomo.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/mbbsd/gomo.c b/mbbsd/gomo.c
new file mode 100644
index 00000000..06062ce4
--- /dev/null
+++ b/mbbsd/gomo.c
@@ -0,0 +1,417 @@
+/* $Id: gomo.c,v 1.1 2002/03/07 15:13:48 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "gomo.h"
+#include "common.h"
+#include "modes.h"
+#include "proto.h"
+
+extern int usernum;
+extern userinfo_t *currutmp;
+
+char ku[BRDSIZ][BRDSIZ];
+static char *chess[] = { "●", "○" };
+static int tick, lastcount, mylasttick, hislasttick;
+
+unsigned char *pat, *adv;
+
+typedef struct {
+ char x;
+ char y;
+} Horder_t;
+
+static Horder_t *v, pool[225];
+
+static void HO_init() {
+ memset(pool, 0, sizeof(pool));
+ v = pool;
+ pat = pat_gomoku;
+ adv = adv_gomoku;
+ memset(ku, 0, sizeof(ku));
+}
+
+static void HO_add(Horder_t *mv) {
+ *v++ = *mv;
+}
+
+static void HO_undo(Horder_t *mv) {
+ char *str = "┌┬┐├┼┤└┴┘";
+ int n1, n2, loc;
+
+ *mv = *(--v);
+ ku[(int)mv->x][(int)mv->y] = BBLANK;
+ BGOTO(mv->x, mv->y);
+ n1 = (mv->x == 0) ? 0 : (mv->x == 14) ? 2 : 1;
+ n2 = (mv->y == 14)? 0 : (mv->y == 0) ? 2 : 1;
+ loc= 2 * ( n2 * 3 + n1);
+ prints("%.2s", str + loc);
+}
+
+extern userec_t cuser;
+
+static void HO_log(char *user) {
+ int i;
+ FILE *log;
+ char buf[80];
+ char buf1[80];
+ char title[80];
+ Horder_t *ptr = pool;
+ extern screenline_t *big_picture;
+ fileheader_t mymail;
+
+ sprintf(buf, "home/%c/%s/F.%d", cuser.userid[0], cuser.userid,
+ rand() & 65535);
+ log = fopen(buf, "w");
+
+ for(i = 1; i < 17; i++)
+ fprintf(log, "%.*s\n", big_picture[i].len, big_picture[i].data);
+
+ i = 0;
+ do {
+ fprintf(log, "[%2d]%s ==> %c%d%c", i + 1, chess[i % 2],
+ 'A' + ptr->x, ptr->y + 1, (i % 2) ? '\n' : '\t');
+ i++;
+ } while( ++ptr < v);
+ fclose(log);
+
+ sethomepath(buf1, cuser.userid);
+ stampfile(buf1, &mymail);
+
+ mymail.savemode = 'H'; /* hold-mail flag */
+ mymail.filemode = FILE_READ;
+ strcpy(mymail.owner, "[備.忘.錄]");
+ sprintf(mymail.title, "\033[37;41m棋譜\033[m %s VS %s",
+ cuser.userid, user);
+ sethomedir(title, cuser.userid);
+ Rename(buf, buf1);
+ append_record(title, &mymail, sizeof(mymail));
+
+ unlink(buf);
+}
+
+static int countgomo() {
+ Horder_t *ptr;
+ int i;
+
+ ptr = pool;
+ i = 0;
+ do {
+ i++;
+ } while(++ptr < v);
+ return i;
+}
+
+static int chkmv(Horder_t *mv, int color, int limit) {
+ char *xtype[] = {"\033[1;31m跳三\033[m", "\033[1;31m活三\033[m",
+ "\033[1;31m死四\033[m", "\033[1;31m跳四\033[m",
+ "\033[1;31m活四\033[m", "\033[1;31m四三\033[m",
+ "\033[1;31m雙三\033[m", "\033[1;31m雙四\033[m",
+ "\033[1;31m雙四\033[m", "\033[1;31m連六\033[m",
+ "\033[1;31m連五\033[m"};
+ int rule = getstyle(mv->x, mv->y, color, limit);
+ if(rule > 1 && rule < 13) {
+ move(15, 40);
+ outs(xtype[rule - 2]);
+ bell();
+ }
+ return chkwin(rule, limit);
+}
+
+static int gomo_key(int fd, int ch, Horder_t *mv) {
+ if( ch >= 'a' && ch <= 'o') {
+ char pbuf[4], vx, vy;
+
+ *pbuf = ch;
+ if(fd)
+ add_io(0, 0);
+ oldgetdata(17, 0, "直接指定位置 :", pbuf, 4, DOECHO);
+ if(fd)
+ add_io(fd, 0);
+ vx = pbuf[0] - 'a';
+ vy = atoi(pbuf + 1) - 1;
+ if(vx >= 0 && vx < 15 && vy >= 0 && vy < 15 &&
+ ku[(int)vx][(int)vy] == BBLANK) {
+ mv->x = vx;
+ mv->y = vy;
+ return 1;
+ }
+ } else {
+ switch(ch) {
+ case KEY_RIGHT:
+ mv->x = (mv->x == BRDSIZ - 1) ? mv->x : mv->x + 1;
+ break;
+ case KEY_LEFT:
+ mv->x = (mv->x == 0 ) ? 0 : mv->x - 1;
+ break;
+ case KEY_UP:
+ mv->y = (mv->y == BRDSIZ - 1) ? mv->y : mv->y + 1;
+ break;
+ case KEY_DOWN:
+ mv->y = (mv->y == 0 ) ? 0 : mv->y - 1;
+ break;
+ case ' ':
+ case '\r':
+ if(ku[(int)mv->x][(int)mv->y] == BBLANK)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+extern userec_t xuser;
+
+static int reload_gomo() {
+ passwd_query(usernum, &xuser);
+ cuser.five_win = xuser.five_win;
+ cuser.five_lose = xuser.five_lose;
+ cuser.five_tie = xuser.five_tie;
+ return 0;
+}
+
+int gomoku(int fd) {
+ Horder_t mv;
+ int me, he, win, ch;
+ int hewantpass, iwantpass;
+ userinfo_t *my = currutmp;
+
+ HO_init();
+ me = !(my->turn) + 1;
+ he = my->turn + 1;
+ win = 1;
+ tick=time(0) + MAX_TIME;
+ lastcount = MAX_TIME;
+ setutmpmode(M_FIVE);
+ clear();
+
+ prints("\033[1;46m 五子棋對戰 \033[45m%30s VS %-30s\033[m",
+ cuser.userid, my->mateid);
+ show_file("etc/@five", 1, -1, ONLY_COLOR);
+ move(11, 40);
+ prints("我是 %s", me == BBLACK ? "先手 ●, 有禁手" : "後手 ○");
+ move(16, 40);
+ prints("\033[1;33m%s", cuser.userid);
+ move(17, 40);
+ prints("\033[1;33m%s", my->mateid);
+
+ reload_gomo();
+ move(16, 60);
+ prints("\033[1;31m%d\033[37m勝 \033[34m%d\033[37m敗 \033[36m%d\033[37m和"
+ "\033[m", cuser.five_win, cuser.five_lose, cuser.five_tie);
+
+ getuser(my->mateid);
+ move(17, 60);
+ prints("\033[1;31m%d\033[37m勝 \033[34m%d\033[37m敗 \033[36m%d\033[37m"
+ "和\033[m", xuser.five_win, xuser.five_lose, xuser.five_tie);
+
+ cuser.five_lose++;
+ /* 一進來先加一場敗場, 贏了後再扣回去, 避免快輸了惡意斷線 */
+ passwd_update(usernum, &cuser);
+
+ add_io(fd, 0);
+
+ hewantpass = iwantpass = 0;
+ mv.x = mv.y = 7;
+ move(18, 40);
+ prints("%s時間還剩%d:%02d\n", my->turn ? "你的" : "對方",
+ MAX_TIME / 60, MAX_TIME % 60);
+ for(;;) {
+ move(13, 40);
+ outs(my->turn ? "輪到自己下了!": "等待對方下子..");
+ if(lastcount != tick-time(0)) {
+ lastcount = tick-time(0);
+ move(18, 40);
+ prints("%s時間還剩%d:%02d\n", my->turn ? "你的" : "對方",
+ lastcount / 60, lastcount % 60);
+ if(lastcount <= 0 && my->turn) {
+ move(19, 40);
+ outs("時間已到, 你輸了");
+ my->five_lose++;
+ send(fd, '\0', 1, 0);
+ break;
+ }
+ if(lastcount <= -5 && !my->turn) {
+ move(19, 40);
+ outs("對手太久沒下, 你贏了!");
+ win = 1;
+ cuser.five_lose--;
+ cuser.five_win++;
+ my->five_win++;
+ passwd_update(usernum, &cuser);
+ mv.x = mv.y = -2;
+ send(fd, &mv, sizeof(Horder_t), 0);
+ mv = *(v - 1);
+ break;
+ }
+ }
+ move(14, 40);
+ if(hewantpass) {
+ outs("\033[1;32m和棋要求!\033[m");
+ bell();
+ } else
+ clrtoeol();
+ BGOTOCUR(mv.x, mv.y);
+ ch = igetkey();
+ if(ch != I_OTHERDATA)
+ iwantpass = 0;
+ if(ch == 'q') {
+ if(countgomo() < 10) {
+ cuser.five_lose--;
+ passwd_update(usernum, &cuser);
+ }
+ send(fd, '\0', 1, 0);
+ break;
+ } else if(ch == 'u' && !my->turn && v > pool) {
+ mv.x = mv.y = -1;
+ ch = send(fd, &mv, sizeof(Horder_t), 0);
+ if(ch == sizeof(Horder_t)) {
+ HO_undo(&mv);
+ tick = mylasttick;
+ my->turn = 1;
+ continue;
+ } else
+ break;
+ }
+ if(ch == 'p') {
+ if(my->turn ) {
+ if(iwantpass == 0) {
+ iwantpass = 1;
+ mv.x = mv.y = -2;
+ send(fd, &mv, sizeof(Horder_t), 0);
+ mv = *(v - 1);
+ }
+ continue;
+ } else if(hewantpass) {
+ win = 0;
+ cuser.five_lose--;
+ cuser.five_tie++;
+ my->five_tie++;
+ passwd_update(usernum, &cuser);
+ mv.x=mv.y=-2;
+ send(fd, &mv, sizeof(Horder_t), 0);
+ mv = *(v - 1);
+ break;
+ }
+ }
+
+ if(ch == I_OTHERDATA) {
+ ch = recv(fd, &mv, sizeof(Horder_t), 0);
+ if(ch != sizeof(Horder_t)) {
+ lastcount=tick-time(0);
+ if(lastcount >=0) {
+ win = 1;
+ cuser.five_lose--;
+ if(countgomo() >=10) {
+ cuser.five_win++;
+ my->five_win++;
+ }
+ passwd_update(usernum, &cuser);
+ outmsg("對方認輸了!!");
+ break;
+ } else {
+ win = 0;
+ outmsg("你超過時間未下子, 輸了!");
+ my->five_lose++;
+ break;
+ }
+ } else if(mv.x == -2 && mv.y == -2) {
+ if(iwantpass == 1) {
+ win = 0;
+ cuser.five_lose--;
+ cuser.five_tie++;
+ my->five_tie++;
+ passwd_update(usernum, &cuser);
+ break;
+ } else {
+ hewantpass = 1;
+ mv = *(v - 1);
+ continue;
+ }
+ }
+ if(my->turn && mv.x == -1 && mv.y == -1) {
+ outmsg("對方悔棋");
+ tick = hislasttick;
+ HO_undo(&mv);
+ my->turn = 0;
+ continue;
+ }
+
+ if(!my->turn) {
+ win = chkmv(&mv, he, he == BBLACK);
+ HO_add(&mv);
+ hislasttick = tick;
+ tick = time(0) + MAX_TIME;
+ ku[(int)mv.x][(int)mv.y] = he;
+ bell();
+ BGOTO(mv.x, mv.y);
+ outs(chess[he - 1]);
+
+ if(win) {
+ outmsg(win == 1 ? "對方贏了!" : "對方禁手");
+ if(win != 1) {
+ cuser.five_lose--;
+ cuser.five_win++;
+ my->five_win++;
+ passwd_update(usernum, &cuser);
+ } else
+ my->five_lose++;
+ win = -win;
+ break;
+ }
+ my->turn = 1;
+ }
+ continue;
+ }
+
+ if(my->turn) {
+ if(gomo_key(fd, ch, &mv))
+ my->turn = 0;
+ else
+ continue;
+
+ if(!my->turn) {
+ HO_add(&mv);
+ BGOTO(mv.x, mv.y);
+ outs(chess[me - 1]);
+ win = chkmv( &mv, me, me == BBLACK);
+ ku[(int)mv.x][(int)mv.y] = me;
+ mylasttick = tick;
+ tick = time(0) + MAX_TIME; /*倒數*/
+ lastcount = MAX_TIME;
+ if(send(fd, &mv, sizeof(Horder_t), 0) != sizeof(Horder_t))
+ break;
+ if(win) {
+ outmsg(win == 1 ? "我贏囉~~" : "禁手輸了" );
+ if(win == 1) {
+ cuser.five_lose--;
+ cuser.five_win++;
+ my->five_win++;
+ passwd_update(usernum, &cuser);
+ } else
+ my->five_lose++;
+ break;
+ }
+ move(15, 40);
+ clrtoeol();
+ }
+ }
+ }
+ add_io(0, 0);
+ close(fd);
+
+ igetch();
+ if(v > pool) {
+ char ans[4];
+
+ getdata(19 , 0, "要保留本局成棋譜嗎?(y/N)", ans, 4, LCECHO);
+ if(*ans == 'y')
+ HO_log(my->mateid);
+ }
+ return 0;
+}