summaryrefslogblamecommitdiffstats
path: root/mbbsd/dark.c
blob: 1b084407ddda4980e2071e86c15fc39c08f70a5c (plain) (tree)
1
                                                     

















































































































                                                                               










                                                    








































































































































































































                                                                                                    







                                                                                                                  
























































































































                                                                                                                                       
/* $Id: dark.c,v 1.2 2002/04/27 15:50:17 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "config.h"
#include "pttstruct.h"
#include "common.h"
#include "proto.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;

static item brd[4][8];                 
static cur  curr;                            /*   6 個 bytes */
extern userinfo_t *currutmp; 

static char *rname[]={"兵","炮","傌","車","相","仕","帥"};
static char *bname[]={"卒","包","馬","車","象","士","將"};

static sint cury[]={3,5,7,9}, curx[]={5,9,13,17,21,25,29,33};
static sint rcount,bcount,cont,fix;              /* cont:是否可連吃 */
static sint my=0,mx=0,mly=-1,mlx=-1;             /* 移動的座標 跟 選子的座標 */

static sint cur_eaty,cur_eatx;           /* 吃掉對方其子的秀出座標 */
static void brdswap(sint y,sint x,sint ly,sint lx) {
    memcpy(&brd[y][x],&brd[ly][lx],sizeof(item));
    brd[ly][lx].die=1;
    brd[ly][lx].color=-1;                  /* 沒這個color */
    brd[ly][lx].value=-1;
}

static void pprints(sint y,sint x,char* s) {
    move(y,x);
    clrtoeol();
    prints("%s",s);
}

static sint Is_win(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 && brd[y][x].die==0)||
       (abs(lx-x)==1 && 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(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(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)) && 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(sint y,sint x, sint ly, sint lx) {
    if(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() {
    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(brd, sizeof(brd));
    bzero(tem, sizeof(tem));
    bzero(&curr, sizeof(curr));
    srand(getpid()%2731+time(NULL)%3219);
    for(y=0;y<4;y++)
    for(x=0;x<8;x++)
        while(1) {
        index=rand()%32;
        if(tem[index]) continue;
        brd[y][x].color=(index>15)?0:1;
        brd[y][x].value=value[index];
        tem[index]=1;
        break;
        }
}

static void brd_prints() {
    clear();
    move(1,0);
    outs("\n"
"   ╭─┬─┬─┬─┬─┬─┬─┬─╮\n"
"   │●│●│●│●│●│●│●│●│\n"
"   ├─┼─┼─┼─┼─┼─┼─┼─┤\n"
"   │●│●│●│●│●│●│●│●│\n"
"   ├─┼─┼─┼─┼─┼─┼─┼─┤\n"
"   │●│●│●│●│●│●│●│●│\n"
"   ├─┼─┼─┼─┼─┼─┼─┼─┤\n"
"   │●│●│●│●│●│●│●│●│\n"
"   ╰─┴─┴─┴─┴─┴─┴─┴─╯\n"
"   ");
}

static void draw_line(sint y, sint f) {
    sint i;
    char  buf[1024],tmp[256];

    *buf = 0;
    *tmp = 0;
    strcpy(buf,"\033[43;30m");
    for(i=0; i<8; i++)
    {
    if(brd[y][i].die==1)
        sprintf(tmp,"│  ");
    else if(brd[y][i].out==0)
        sprintf(tmp,"│●");
    else {
        sprintf(tmp, "│\033[%s1;%dm%s\033[m\033[43;30m",
            (f==i)?"1;47;":"",(brd[y][i].color)?31:34,
            (brd[y][i].color)?rname[brd[y][i].value]:
            bname[brd[y][i].value]);
    }
    strcat(buf,tmp);
    }
    strcat(buf,"│\033[m");

    move(cury[y],3);
    clrtoeol();
    prints("%s",buf);
}

static void redraw() {
    sint i=0;
    for(;i<4;i++)
    draw_line(i,-1);
}

static sint playing(sint fd, sint color,sint ch,sint *b, userinfo_t *uin) {
    curr.end = 0;
    move(cury[my],curx[mx]);

    if(fix) {
    if(ch=='s') {
        fix=0; *b=0; return 0;
    } else {
        draw_line(mly,-1);
    }
    }

    switch(ch) {
    case KEY_LEFT:
    if(mx == 0) mx=7;
    else mx--;
    move(cury[my],curx[mx]);
    *b=-1;
    break;
    case KEY_RIGHT:
    if(mx==7) mx=0;
    else mx++;
    move(cury[my],curx[mx]);
    *b=-1;
    break;
    case KEY_UP:
    if(my==0) my=3;
    else my--;
    move(cury[my],curx[mx]);
    *b=-1;
    break;
    case KEY_DOWN:
    if(my==3) my=0;
    else my++;
    move(cury[my],curx[mx]);
    *b=-1;
    break;
    case 'q':case 'Q':
    if(!color) bcount=0;
    else rcount=0;
    *b=0;
    return -2;
    case 'p':case 'P':
    return -3;
    case 'c':
    return -4;
    case 'g':
    return -5;
    case 's':                     /* 翻開棋子 或是選擇棋子 */
    /* 選擇棋子 */
    if(brd[my][mx].out==1)
    {
        if(brd[my][mx].color != color)
        {
        *b=-1;
        break;
        }
        if(mly<0)  /*可以選擇*/
        {
        mly=my;mlx=mx;
        draw_line(my,mx);
        *b=-1;
        break;
        }
        else if(mly == my && mlx == mx) /*不選了*/
        {
        mly=-1;mlx=-1;
        draw_line(my,-1);
        }else
        {
        draw_line(mly,-1);
        mly=my;mlx=mx;
        if(brd[mly][mlx].value == 1) fix=1;
        draw_line(my,mx);
        }
        *b=-1;
        break;
    }
    /* 翻開棋子 */
    if(mly >=0 ){ *b=-1; break;}   /*本來就是翻開的*/
    /* 決定一開始的顏色 */
    if(currutmp->color=='.'){
        if(uin->color!='1' && uin->color!='0')
        currutmp->color=(brd[my][mx].color)?'1':'0';
        else
        currutmp->color=(uin->color=='0')?'1':'0';}
    brd[my][mx].out=1;
    draw_line(my,-1);
    move(cury[my],curx[mx]);
    *b=0;
    break;
    case 'u':
    move(0,0);clrtoeol();
    prints("%s色%s cont=%d",(brd[my][mx].color == RED)?"紅":"黑",rname[brd[my][mx].value],cont);
    *b=-1;
    break;
    case '\r':                       /* 吃 or 移動  ly跟lx必須大於0*/
    case '\n':
    if(
        mly >= 0                               /* 要先選子 */
        &&
        brd[mly][mlx].color != brd[my][mx].color  /* 同色不能移動也不能吃 */
        &&
        (Is_move(my,mx,mly,mlx) || Is_win(brd[mly][mlx],brd[my][mx],my,mx,mly,mlx))
        )
    {
        if(fix && brd[my][mx].value<0)
        {
        *b=-1;return 0;
        }
        if(brd[my][mx].value>=0&&brd[my][mx].die==0)
        {
        if(!color) bcount--;
        else rcount--;
        move(cur_eaty,cur_eatx);
        prints("%s",(color)?bname[brd[my][mx].value]:rname[brd[my][mx].value]);
        if(cur_eatx>=26)
        { cur_eatx=5;cur_eaty++; }
        else
            cur_eatx+=3;
        }
        brdswap(my,mx,mly,mlx);
        draw_line(mly,-1);
        draw_line( my,-1);
        if(fix==1) *b=-1;
        else { mly=-1;mlx=-1;*b=0; }
    }
    else *b=-1;
    break;
    default:
    *b=-1;
    }
  
    if(!rcount)
    return -1;
    else if(!bcount)
    return -1;
    if(*b == -1) return 0;
    curr.y = my;curr.x = mx; curr.end=(!*b)?1:0;
    send(fd,&curr,sizeof(curr),0);
    send(fd,&brd,sizeof(brd),0);
    return 0;
}

int main_dark(int fd,userinfo_t *uin) {
    sint end=0,ch=1,go_on,i=0,cont=0;
    char buf[16];
    *buf=0;fix=0;
    currutmp->color='.';   // '.' 表示還沒決定顏色
    rcount=16;bcount=16;   // initialize
    cur_eaty=18,cur_eatx=5;
    brd_prints();
    if(currutmp->turn)
    {
    brd_rand();
    send(fd,&brd,sizeof(brd),0);
    pprints(21,0,"   ◆你是先手");
    pprints(22,0,"   ◆輪到你下了");
    }else
    {
    recv(fd,&brd,sizeof(brd),0);
    pprints(21,0,"   ◆你是後手");
    }
    move(12,3);
    prints("%s[0勝0敗]vs.%s[0勝0敗]",currutmp->userid,currutmp->mateid);
    outs("\n"
"                                                ╳╱功\能表╲╳╲╱╳╲\n"
"                                                ╱ ↑←↓→: 移動\n"
"                                                ╳ s:       選子,翻子\n"
"                                                ╱ enter:    吃棋,放棋\n"
" 已經解決的:                                 ╳ p:       合棋\n"
"                                              ╱ q:       認輸\n"
"                                                ╳ c:       換邊");

    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 = igetkey();
    if(ch == I_OTHERDATA)
    {
        ch=recv(fd,&curr,sizeof(curr),0);
        if(ch!=sizeof(curr))
        {
        if(uin->turn=='e') { end=-3;break; }
        else if(uin->turn!='w') { end=-1; currutmp->turn='w'; break; }
        end=-1; break;
        }

        if(curr.end==-3)      pprints(23,30,"\033[33m要求合棋\033[m");
        else if(curr.end==-4) pprints(23,30,"\033[33m要求換邊\033[m");
        else if(curr.end==-5) pprints(23,30,"\033[33m要求連吃\033[m");
        else pprints(23,30,"");

        recv(fd,&brd,sizeof(brd),0);
        my=curr.y;mx=curr.x;
        redraw();
        if(curr.end)
        pprints(22,0,"   ◆輪到你下了");
        move(cury[my],curx[mx]);
    }else
    {
        if(currutmp->turn=='p')
        {
        if(ch=='y') { end=-3; currutmp->turn='e'; break; }
        else { pprints(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';
        pprints(21,0,(currutmp->color=='1')?"   \033[1;33m◆你持紅色棋\033[m":"   \033[1;33m◆你持黑色棋\033[m");
        }
        else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; }
        }else if(currutmp->turn=='g')
        {
        if(ch=='y') {
            cont=1;
            pprints(21,0,"   \033[1;33m◆你持紅色棋\033[m 可連吃");
        }
        else { pprints(23,30,""); currutmp->turn=(uin->turn)?0:1; }
        }

        if(currutmp->turn==1)
        {
        if(uin->turn=='g') { cont=1;uin->turn=(currutmp->turn)?0:1; pprints(21,10,"可連吃"); }
        end=playing(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';curr.end=-3;
            send(fd,&curr,sizeof(curr),0);
            send(fd,&brd,sizeof(buf),0);
            continue;
        }
        else if(end == -4) {
            if(currutmp->color!='1'&&currutmp->color!='0')
            continue;
            uin->turn='c';i=0;curr.end=-4;
            send(fd,&curr,sizeof(curr),0);
            send(fd,&brd,sizeof(buf),0);
            continue;
        }
        else if(end == -5) {
            uin->turn='g';curr.end=-5;
            send(fd,&curr,sizeof(curr),0);
            send(fd,&brd,sizeof(buf),0);
            continue;
        }
        if(!i && currutmp->color=='1')
        { pprints(21,0,"   \033[1;33m◆你持紅色棋\033[m");i++;move(cury[my],curx[mx]); }
        if(!i && currutmp->color=='0')
        { pprints(21,0,"   \033[1;33m◆你持黑色棋\033[m");i++;move(cury[my],curx[mx]); }

        if(uin->turn == 'e') { end=-3; break; }
        if(go_on < 0) continue;

        move(22,0);clrtoeol();
        prints("   ◆輪到%s下 別怕別怕 他算啥米",currutmp->mateid);
        currutmp->turn = 0;
        uin->turn = 1;
        }else
        {
        if(ch == 'q'){uin->turn='w';break;}
        move(22,0);clrtoeol();
        prints("   ◆輪到%s下 別怕別怕 他算啥米",currutmp->mateid);
        }
    }
    }

    switch(end)
    {
    case -1:
    case -2:
        if(currutmp->turn=='w'){ move(22,0);clrtoeol();prints("你贏了.. 真是恭喜~~");}
        else {move(22,0);clrtoeol();prints("輸掉了啦.....下次讓他好看!!");}
        break;
    case -3:
        pprints(22,0,"合棋唷!! 下次在分高下吧 ^_^");
        break;
    default:
        add_io(0,0);
        close(fd);
        pressanykey();
        return 0;
    }
    add_io(0,0);
    close(fd);
    pressanykey();
    return 0;
}