/* $Id: dark.c,v 1.8 2002/07/22 19:02:00 in2 Exp $ */
#include "bbs.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 */

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�� �� */

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;
    strlcpy(buf, "\033[43;30m", sizeof(buf));
    for (i = 0; i < 8; i++) {
	if (brd[y][i].die == 1)
	    snprintf(tmp, sizeof(tmp), "�x  ");
	else if (brd[y][i].out == 0)
	    snprintf(tmp, sizeof(tmp), "�x��");
	else {
	    snprintf(tmp, sizeof(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;
}