/* $Id: dark.c,v 1.3 2002/05/13 03:20:04 ptt 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
extern time_t now;
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[]={"�L","��","�X","��","��","�K","��"};
static char *bname[]={"��","�]","��","��","�H","�h","�N"};

static sint cury[]={3,5,7,9}, curx[]={5,9,13,17,21,25,29,33};
static sint rcount,bcount,cont,fix;              /* cont:�O�_�i�s�Y */
static sint my=0,mx=0,mly=-1,mlx=-1;             /* ���ʪ��y�� �� ��l���y�� */

static sint cur_eaty,cur_eatx;			 /* �Y������l���q�X�y�� */
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;                  /* �S�o��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;
    }
    /* �D�� */
    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+now%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"
"   �~�w�s�w�s�w�s�w�s�w�s�w�s�w�s�w��\n"
"   �x���x���x���x���x���x���x���x���x\n"
"   �u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t\n"
"   �x���x���x���x���x���x���x���x���x\n"
"   �u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t\n"
"   �x���x���x���x���x���x���x���x���x\n"
"   �u�w�q�w�q�w�q�w�q�w�q�w�q�w�q�w�t\n"
"   �x���x���x���x���x���x���x���x���x\n"
"   ���w�r�w�r�w�r�w�r�w�r�w�r�w�r�w��\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,"�x  ");
	else if(brd[y][i].out==0)
	    sprintf(tmp,"�x��");
	else {
	    sprintf(tmp, "�x\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,"�x\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':                     /* ½�}�Ѥl �άO��ܴѤl */
	/* ��ܴѤl */
	if(brd[my][mx].out==1)
	{
	    if(brd[my][mx].color != color)
	    {
		*b=-1;
		break;
	    }
	    if(mly<0)  /*�i�H���*/
	    {
		mly=my;mlx=mx;
		draw_line(my,mx);
		*b=-1;
		break;
	    }
	    else if(mly == my && mlx == mx) /*����F*/
	    {
		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;
	}
	/* ½�}�Ѥl */
	if(mly >=0 ){ *b=-1; break;}   /*���ӴN�O½�}��*/
	/* �M�w�@�}�l���C�� */
	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':                       /* �Y or ����  ly��lx�����j��0*/
    case '\n':
	if(
	    mly >= 0                               /* �n����l */
	    &&
	    brd[mly][mlx].color != brd[my][mx].color  /* �P�⤣�ಾ�ʤ]����Y */
	    &&
	    (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='.';   // '.' �����٨S�M�w�C��
    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,"   ���A�O����");
	pprints(22,0,"   ������A�U�F");
    }else
    {
	recv(fd,&brd,sizeof(brd),0);
	pprints(21,0,"   ���A�O���");
    }
    move(12,3);
    prints("%s[0��0��]����.%s[0��0��]",currutmp->userid,currutmp->mateid);
    outs("\n"
"                                                �����\\���������������\n"
"                                                �� ��������: ����\n"
"                                                �� ��:       ��l,½�l\n"
"                                                �� enter:    �Y��,���\n"
"�@�w�g�ѨM��:�@�@                               �� ��:       �X��\n"
"                                       �@�@     �� ��:       �{��\n"
"                                                �� ��:       ����");

    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�n�D�X��\033[m");
	    else if(curr.end==-4) pprints(23,30,"\033[33m�n�D����\033[m");
	    else if(curr.end==-5) pprints(23,30,"\033[33m�n�D�s�Y\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,"   ������A�U�F");
	    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���A�������\033[m":"   \033[1;33m���A���¦��\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���A�������\033[m �i�s�Y");
		}
		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,"�i�s�Y"); }
		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���A�������\033[m");i++;move(cury[my],curx[mx]); }
		if(!i && currutmp->color=='0')
		{ pprints(21,0,"   \033[1;33m���A���¦��\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�U �O�ȧO�� �L��ԣ��",currutmp->mateid);
		currutmp->turn = 0;
		uin->turn = 1;
	    }else
	    {
		if(ch == 'q'){uin->turn='w';break;}
		move(22,0);clrtoeol();
		prints("   ������%s�U �O�ȧO�� �L��ԣ��",currutmp->mateid);
	    }
	}
    }

    switch(end)
    {
    case -1:
    case -2:
        if(currutmp->turn=='w'){ move(22,0);clrtoeol();prints("�A�F.. �u�O����~~");}
        else {move(22,0);clrtoeol();prints("�鱼�F��.....�U�����L�n��!!");}
        break;
    case -3:
        pprints(22,0,"�X�ѭ�!! �U���b�����U�a ^_^");
        break;
    default:
        add_io(0,0);
        close(fd);
        pressanykey();
        return 0;
    }
    add_io(0,0);
    close(fd);
    pressanykey();
    return 0;
}