/****************************************************************************
* Lands of Altanos by Jeff Maxx *
***************************************************************************/
/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops, Fireblade, Edmond, Conran | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include "mud.h"
#define SC_VERSION "5.65"
#define SC_INFO "MUD Chess"
#ifndef GET_NAME
#define GET_NAME(ch) (ch)->name
#endif
#define CHESS_NAME(ch,board) (board->type==TYPE_IMC?ch:GET_NAME(ch))
#define STOCK_COLOR /* Uncomment */
#define send_to_char send_to_char_color
#define WHITE_BACKGROUND ""
#define BLACK_BACKGROUND ""
#define WHITE_FOREGROUND ""
#define BLACK_FOREGROUND ""
#ifdef USE_IMC
#include "imc.h"
#include "imc-mercbase.h"
void setdata(imc_packet *p, const imc_char_data *d);
const imc_char_data *getdata(CHAR_DATA *ch);
const char *getname(CHAR_DATA *ch, const imc_char_data *vict);
void imc_recv_chess(const imc_char_data *from, const char *to, const char *argument);
void imc_send_chess(CHAR_DATA *ch, const char *to, const char *argument);
#endif
const char *big_pieces[MAX_PIECES][2] = {
{ "%s ",
"%s " },
{ "%s (-) ",
"%s -|- " },
{ "%s ### ",
"%s { } " },
{ "%s /-*- ",
"%s / / " },
{ "%s () + ",
"%s {}-| " },
{ "%s @ ",
"%s /+\\ " },
{ "%s ^^^^^^ ",
"%s {@} " },
{ "%s [-] ",
"%s -|- " },
{ "%s ### ",
"%s [ ] " },
{ "%s /-*- ",
"%s / / " },
{ "%s [] + ",
"%s {}-| " },
{ "%s # ",
"%s /+\\ " },
{ "%s ^^^^^^ ",
"%s [#] " }
};
const char small_pieces[MAX_PIECES+1] = " prnbqkPRNBQK";
static char *print_big_board(CHAR_DATA *ch, GAME_BOARD_DATA *board)
{
static char retbuf[MAX_STRING_LENGTH*2];
char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
char s1[16], s2[16];
int x,y;
sprintf(s1,"&Y&W");
sprintf(s2,"&z&z");
sprintf(retbuf,WHITE_FOREGROUND "\n\r&g 1 2 3 4 5 6 7 8\n\r");
for (x=0;x<8;x++)
{
strcat(retbuf," ");
for (y=0;y<8;y++)
{
sprintf(buf,"%s%s",
x%2==0 ? (y%2==0 ? BLACK_BACKGROUND : WHITE_BACKGROUND) : \
(y%2==0 ? WHITE_BACKGROUND : BLACK_BACKGROUND),
big_pieces[board->board[x][y]][0]);
sprintf(buf2,buf,IS_WHITE(board->board[x][y]) ? s1 : s2);
strcat(retbuf,buf2);
}
strcat(retbuf, BLACK_BACKGROUND "\n\r");
sprintf(buf, WHITE_FOREGROUND "&g%c ", 'A'+x);
strcat(retbuf,buf);
for (y=0;y<8;y++)
{
sprintf(buf,"%s%s",
x%2==0 ? (y%2==0 ? BLACK_BACKGROUND : WHITE_BACKGROUND) : \
(y%2==0 ? WHITE_BACKGROUND : BLACK_BACKGROUND),
big_pieces[board->board[x][y]][1]);
sprintf(buf2,buf,IS_WHITE(board->board[x][y]) ? s1 : s2);
strcat(retbuf,buf2);
}
strcat(retbuf, BLACK_BACKGROUND "\n\r");
}
return(retbuf);
}
static void init_board(GAME_BOARD_DATA *board)
{
int x,y;
for (x=0;x<8;x++)
for (y=0;y<8;y++)
board->board[x][y] = 0;
board->board[0][0] = WHITE_ROOK;
board->board[0][1] = WHITE_KNIGHT;
board->board[0][2] = WHITE_BISHOP;
board->board[0][3] = WHITE_QUEEN;
board->board[0][4] = WHITE_KING;
board->board[0][5] = WHITE_BISHOP;
board->board[0][6] = WHITE_KNIGHT;
board->board[0][7] = WHITE_ROOK;
for (x=0;x<8;x++)
board->board[1][x] = WHITE_PAWN;
for (x=0;x<8;x++)
board->board[6][x] = BLACK_PAWN;
board->board[7][0] = BLACK_ROOK;
board->board[7][1] = BLACK_KNIGHT;
board->board[7][2] = BLACK_BISHOP;
board->board[7][3] = BLACK_QUEEN;
board->board[7][4] = BLACK_KING;
board->board[7][5] = BLACK_BISHOP;
board->board[7][6] = BLACK_KNIGHT;
board->board[7][7] = BLACK_ROOK;
board->player1 = NULL;
board->player2 = NULL;
board->turn = 0;
board->type = TYPE_LOCAL;
}
static bool find_piece(GAME_BOARD_DATA *board, int *x, int *y, int piece)
{
int a,b;
for (a=0;a<8;a++)
{
for (b=0;b<8;b++)
if (board->board[a][b] == piece)
break;
if (board->board[a][b] == piece)
break;
}
*x = a;
*y = b;
if (board->board[a][b] == piece)
return TRUE;
return FALSE;
}
#define SAME_COLOR(x1,y1,x2,y2) \
((IS_WHITE(board->board[x1][y1]) && IS_WHITE(board->board[x2][y2])) || \
(IS_BLACK(board->board[x1][y1]) && IS_BLACK(board->board[x2][y2])))
static bool king_in_check(GAME_BOARD_DATA *board, int piece)
{
int x=0,y=0,l,m;
if ( piece != WHITE_KING && piece != BLACK_KING )
return FALSE;
if (!find_piece(board,&x,&y,piece))
return FALSE;
if ( x<0 || y<0 || x>7 || y>7 )
return FALSE;
/* pawns */
if ( IS_WHITE(piece) && x < 7 &&
(( y > 0 && IS_BLACK(board->board[x+1][y-1]) ) ||
( y < 7 && IS_BLACK(board->board[x+1][y+1]) )))
return TRUE;
else if ( IS_BLACK(piece) && x > 0 &&
(( y > 0 && IS_WHITE(board->board[x-1][y-1]) ) ||
( y < 7 && IS_WHITE(board->board[x-1][y+1]) )))
return TRUE;
/* knights */
if ( x-2 >= 0 && y-1 >= 0 &&
( (board->board[x-2][y-1] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x-2][y-1] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x-2 >= 0 && y+1 < 8 &&
( (board->board[x-2][y+1] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x-2][y+1] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x-1 >= 0 && y-2 >= 0 &&
( (board->board[x-1][y-2] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x-1][y-2] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x-1 >= 0 && y+2 < 8 &&
( (board->board[x-1][y+2] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x-1][y+2] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x+1 < 8 && y-2 >= 0 &&
( (board->board[x+1][y-2] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x+1][y-2] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x+1 < 8 && y+2 < 8 &&
( (board->board[x+1][y+2] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x+1][y+2] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x+2 < 8 && y-1 >= 0 &&
( (board->board[x+2][y-1] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x+2][y-1] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
if ( x+2 < 8 && y+1 < 8 &&
( (board->board[x+2][y+1] == BLACK_KNIGHT && IS_WHITE(board->board[x][y])) ||
(board->board[x+2][y+1] == WHITE_KNIGHT && IS_BLACK(board->board[x][y])) ))
return TRUE;
/* horizontal/vertical long distance */
for (l=x+1;l<8;l++)
if ( board->board[l][y] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,y) )
break;
if ( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN ||
board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK )
return TRUE;
break;
}
for (l=x-1;l>=0;l--)
if ( board->board[l][y] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,y) )
break;
if ( board->board[l][y] == BLACK_QUEEN || board->board[l][y] == WHITE_QUEEN ||
board->board[l][y] == BLACK_ROOK || board->board[l][y] == WHITE_ROOK )
return TRUE;
break;
}
for (m=y+1;m<8;m++)
if ( board->board[x][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,x,m) )
break;
if ( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN ||
board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK )
return TRUE;
break;
}
for (m=y-1;m>=0;m--)
if ( board->board[x][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,x,m) )
break;
if ( board->board[x][m] == BLACK_QUEEN || board->board[x][m] == WHITE_QUEEN ||
board->board[x][m] == BLACK_ROOK || board->board[x][m] == WHITE_ROOK )
return TRUE;
break;
}
/* diagonal long distance */
for (l=x+1,m=y+1;l<8 && m<8;l++,m++)
if ( board->board[l][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,m) )
break;
if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN ||
board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP )
return TRUE;
break;
}
for (l=x-1,m=y+1;l>=0 && m<8;l--,m++)
if ( board->board[l][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,m) )
break;
if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN ||
board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP )
return TRUE;
break;
}
for (l=x+1,m=y-1;l<8 && m>=0;l++,m--)
if ( board->board[l][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,m) )
break;
if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN ||
board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP )
return TRUE;
break;
}
for (l=x-1,m=y-1;l>=0 && m>=0;l--,m--)
if ( board->board[l][m] != NO_PIECE )
{
if ( SAME_COLOR(x,y,l,m) )
break;
if ( board->board[l][m] == BLACK_QUEEN || board->board[l][m] == WHITE_QUEEN ||
board->board[l][m] == BLACK_BISHOP || board->board[l][m] == WHITE_BISHOP )
return TRUE;
break;
}
return FALSE;
}
static bool king_in_checkmate(GAME_BOARD_DATA *board, int piece)
{
int x=0,y=0,dx,dy,sk=0;
if ( piece != WHITE_KING && piece != BLACK_KING )
return FALSE;
if (!find_piece(board,&x,&y,piece))
return FALSE;
if ( x<0 || y<0 || x>7 || y>7 )
return FALSE;
if (!king_in_check(board,board->board[x][y]))
return FALSE;
dx = x+1;
dy = y+1;
if ( dx < 8 && dy < 8 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x-1;
dy = y+1;
if ( dx >= 0 && dy < 8 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x+1;
dy = y-1;
if ( dx < 8 && dy >= 0 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x-1;
dy = y-1;
if ( dx >= 0 && dy >= 0 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x;
dy = y+1;
if ( dy < 8 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x;
dy = y-1;
if ( dy >= 0 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x+1;
dy = y;
if ( dx < 8 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
dx = x-1;
dy = y;
if ( dx >= 0 && board->board[dx][dy] == NO_PIECE )
{
sk = board->board[dx][dy] = board->board[x][y];
board->board[x][y] = NO_PIECE;
if (!king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
return FALSE;
}
board->board[x][y] = sk;
board->board[dx][dy] = NO_PIECE;
}
return TRUE;
}
static int is_valid_move(CHAR_DATA *ch, GAME_BOARD_DATA *board, int x, int y, int dx, int dy)
{
if ( dx<0 || dy<0 || dx>7 || dy>7 )
return MOVE_OFFBOARD;
if ( board->board[x][y] == NO_PIECE )
return MOVE_INVALID;
if ( x == dx && y == dy )
return MOVE_INVALID;
if ( IS_WHITE(board->board[x][y]) && board->player1 == ch )
return MOVE_WRONGCOLOR;
if ( IS_BLACK(board->board[x][y]) && (board->player2 == ch || !ch) )
return MOVE_WRONGCOLOR;
switch (board->board[x][y])
{
case WHITE_PAWN: case BLACK_PAWN:
if ( IS_WHITE(board->board[x][y]) &&
dx == x+2 && x == 1 && dy == y &&
board->board[dx][dy] == NO_PIECE &&
board->board[x+1][dy] == NO_PIECE )
return MOVE_OK;
else if ( IS_BLACK(board->board[x][y]) &&
dx == x-2 && x == 6 && dy == y &&
board->board[dx][dy] == NO_PIECE &&
board->board[x-1][dy] == NO_PIECE )
return MOVE_OK;
if ( IS_WHITE(board->board[x][y]) && dx != x+1 )
return MOVE_INVALID;
else if ( IS_BLACK(board->board[x][y]) && dx != x-1 )
return MOVE_INVALID;
if ( dy != y && dy != y-1 && dy != y+1 )
return MOVE_INVALID;
if ( dy == y )
{
if ( board->board[dx][dy] == NO_PIECE)
return MOVE_OK;
else if ( SAME_COLOR(x,y,dx,dy) )
return MOVE_SAMECOLOR;
else
return MOVE_BLOCKED;
}
else
{
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_INVALID;
else if ( SAME_COLOR(x,y,dx,dy) )
return MOVE_SAMECOLOR;
else if ( board->board[dx][dy] != BLACK_KING &&
board->board[dx][dy] != WHITE_KING )
return MOVE_TAKEN;
else
return MOVE_INVALID;
}
break;
case WHITE_ROOK: case BLACK_ROOK:
{
int cnt;
if ( dx != x && dy != y )
return MOVE_INVALID;
if ( dx == x)
{
for (cnt = y; cnt != dy; )
{
if ( cnt != y && board->board[x][cnt] != NO_PIECE )
return MOVE_BLOCKED;
if ( dy > y )
cnt++;
else
cnt--;
}
}
else if ( dy == y)
{
for (cnt = x; cnt != dx; )
{
if ( cnt !=x && board->board[cnt][y] != NO_PIECE )
return MOVE_BLOCKED;
if ( dx > x )
cnt++;
else
cnt--;
}
}
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_OK;
if ( !SAME_COLOR(x,y,dx,dy) )
return MOVE_TAKEN;
return MOVE_SAMECOLOR;
}
break;
case WHITE_KNIGHT: case BLACK_KNIGHT:
if ( (dx == x-2 && dy == y-1) ||
(dx == x-2 && dy == y+1) ||
(dx == x-1 && dy == y-2) ||
(dx == x-1 && dy == y+2) ||
(dx == x+1 && dy == y-2) ||
(dx == x+1 && dy == y+2) ||
(dx == x+2 && dy == y-1) ||
(dx == x+2 && dy == y+1) )
{
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_OK;
if ( SAME_COLOR(x,y,dx,dy) )
return MOVE_SAMECOLOR;
return MOVE_TAKEN;
}
return MOVE_INVALID;
break;
case WHITE_BISHOP: case BLACK_BISHOP:
{
int l, m, blocked = FALSE;
if ( dx == x || dy == y )
return MOVE_INVALID;
l = x;
m = y;
while ( 1 )
{
if ( dx > x )
l++;
else
l--;
if ( dy > y )
m++;
else
m--;
if ( l > 7 || m > 7 || l < 0 || m < 0 )
return MOVE_INVALID;
if ( l == dx && m == dy )
break;
if ( board->board[l][m] != NO_PIECE )
blocked = TRUE;
}
if ( l != dx || m != dy )
return MOVE_INVALID;
if ( blocked )
return MOVE_BLOCKED;
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_OK;
if ( !SAME_COLOR(x,y,dx,dy) )
return MOVE_TAKEN;
return MOVE_SAMECOLOR;
}
break;
case WHITE_QUEEN: case BLACK_QUEEN:
{
int l, m, blocked = FALSE;
l = x;
m = y;
while ( 1 )
{
if ( dx > x )
l++;
else if ( dx < x )
l--;
if ( dy > y )
m++;
else if ( dy < y )
m--;
if ( l > 7 || m > 7 || l < 0 || m < 0 )
return MOVE_INVALID;
if ( l == dx && m == dy )
break;
if ( board->board[l][m] != NO_PIECE )
blocked = TRUE;
}
if ( l != dx || m != dy )
return MOVE_INVALID;
if ( blocked )
return MOVE_BLOCKED;
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_OK;
if ( !SAME_COLOR(x,y,dx,dy) )
return MOVE_TAKEN;
return MOVE_SAMECOLOR;
}
break;
case WHITE_KING: case BLACK_KING:
{
int sp,sk;
if ( dx > x+1 || dx < x-1 || dy > y+1 || dy < y-1 )
return MOVE_INVALID;
sk = board->board[x][y];
sp = board->board[dx][dy];
board->board[x][y] = sp;
board->board[dx][dy] = sk;
if (king_in_check(board,sk))
{
board->board[x][y] = sk;
board->board[dx][dy] = sp;
return MOVE_CHECK;
}
board->board[x][y] = sk;
board->board[dx][dy] = sp;
if ( board->board[dx][dy] == NO_PIECE )
return MOVE_OK;
if ( SAME_COLOR(x,y,dx,dy) )
return MOVE_SAMECOLOR;
return MOVE_TAKEN;
}
break;
default: bug("Invaild piece: %d", board->board[x][y]);
return MOVE_INVALID;
}
if ((IS_WHITE(board->board[x][y]) && IS_WHITE(board->board[dx][dy])) ||
(IS_BLACK(board->board[x][y]) && IS_BLACK(board->board[dx][dy])))
return MOVE_SAMECOLOR;
return MOVE_OK;
}
#undef SAME_COLOR
void free_game( GAME_BOARD_DATA *board )
{
if ( !board )
return;
#ifdef USE_IMC
if ( board->type == TYPE_IMC )
{
imc_send_chess((CHAR_DATA *)board->player1?:NULL, (char *)board->player2, "stop");
if (board->player2)
DISPOSE(board->player2);
}
#endif
if ( board->player1 )
{
CHAR_DATA *ch = (CHAR_DATA *)board->player1;
ch_printf(ch, "The game has been stopped at %d total moves.\n\r", board->turn);
ch->pcdata->game_board = NULL;
}
if ( board->player2 )
{
CHAR_DATA *ch = (CHAR_DATA *)board->player2;
ch_printf(ch, "The game has been stopped at %d total moves.\n\r", board->turn);
ch->pcdata->game_board = NULL;
}
board->player1 = NULL;
board->player2 = NULL;
DISPOSE(board);
}
#ifdef USE_IMC
void imc_send_chess(CHAR_DATA *ch, const char *to, const char *argument)
{
imc_packet out;
if ( !ch || imc_active<IA_UP )
return;
setdata(&out, getdata(ch));
imc_sncpy(out.to, to, IMC_NAME_LENGTH);
strcpy(out.type, "chess");
imc_addkey(&out.data, "text", argument);
imc_send(&out);
imc_freedata(&out.data);
}
void imc_recv_chess(const imc_char_data *from, const char *to, const char *argument)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim, *vch;
char buf[MAX_INPUT_LENGTH];
if ( !strcmp(to, "*") )
return;
victim=NULL;
for ( d=descriptor_list; d; d=d->next )
{
if ( d->connected==CON_PLAYING &&
(vch=d->original ? d->original : d->character)!=NULL &&
!IS_NPC(vch) )
{
if ( !str_cmp((char *)to, GET_NAME(vch)) )
{
victim=vch;
break;
}
if ( is_name((char *)to, GET_NAME(vch)) )
victim=vch;
}
}
if ( !victim )
{
if ( !str_cmp(argument, "stop") )
return;
sprintf(buf, "%s is not here.", to);
imc_send_tell(NULL, from->name, buf, 1);
return;
}
if ( !victim->pcdata->game_board )
{
if ( !str_cmp(argument, "stop") )
return;
sprintf(buf, "%s is not ready to be joined in a game.", to);
imc_send_tell(NULL, from->name, buf, 1);
imc_send_chess((CHAR_DATA *)victim->pcdata->game_board->player1?:NULL,(char *)from->name,"stop");
return;
}
if ( !str_cmp(argument, "start") )
{
if ( victim->pcdata->game_board->player2 != NULL )
{
sprintf(buf, "%s is already playing a game.", to);
imc_send_tell(NULL, from->name, buf, 1);
imc_send_chess((CHAR_DATA *)victim->pcdata->game_board->player1?:NULL,(char *)from->name,"stop");
return;
}
victim->pcdata->game_board->player2 = str_dup(from->name);
victim->pcdata->game_board->turn = 0;
victim->pcdata->game_board->type = TYPE_IMC;
ch_printf(victim, "%s has joined your game.\n\r", from->name);
imc_send_chess(victim, from->name, "accepted");
return;
}
if ( !str_cmp(argument, "accepted") )
{
if ( !victim->pcdata->game_board ||
victim->pcdata->game_board->player2 == NULL ||
victim->pcdata->game_board->type != TYPE_IMC ||
str_cmp((char *)victim->pcdata->game_board->player2,from->name) )
{
imc_send_chess((CHAR_DATA *)victim->pcdata->game_board->player1?:NULL,(char *)from->name, "stop");
return;
}
ch_printf(victim,"You have joined %s in a game.\n\r", from->name);
if (victim->pcdata->game_board->player2)
DISPOSE(victim->pcdata->game_board->player2);
victim->pcdata->game_board->player2 = str_dup(from->name);
victim->pcdata->game_board->turn = 1;
return;
}
if ( !str_cmp(argument, "stop") )
{
ch_printf(victim, "%s has stopped the game.\n\r", from->name);
free_game(victim->pcdata->game_board);
return;
}
if ( !str_cmp(argument, "invalidmove") )
{
send_to_char("You have issued an invalid move according to the other mud.\n\r", victim);
do_game_board(victim,"stop",0);
return;
}
if ( !str_cmp(argument, "moveok") )
{
send_to_char("The other mud has accepted your move.\n\r", victim);
return;
}
if ( !str_prefix("move", argument) )
{
char a,b;
int x,y,dx,dy,ret;
a=b=' ';
x=y=dx=dy=-1;
if (sscanf(argument, "move %c%d %c%d",&a,&y,&b,&dy) != 4 ||
a<'0' || a>'7' || b<'0' || b>'7' || y<0 || y>7 || dy<0 || dy>7)
{
imc_send_chess((CHAR_DATA *)victim->pcdata->game_board->player1?:NULL,(char *)from->name, "invalidmove");
return;
}
x = a - '0';
dx = b - '0';
x = (7-x);
y = (7-y);
dx = (7-dx);
dy = (7-dy);
log_printf("%d, %d -> %d, %d", x,y,dx,dy);
ret = is_valid_move(NULL,victim->pcdata->game_board,x,y,dx,dy);
if (ret == MOVE_OK || ret == MOVE_TAKEN)
{
GAME_BOARD_DATA *board;
int piece, destpiece;
board = victim->pcdata->game_board;
piece = board->board[x][y];
destpiece = board->board[dx][dy];
board->board[dx][dy] = piece;
board->board[x][y] = NO_PIECE;
if ( king_in_check(board,IS_WHITE(board->board[dx][dy])?WHITE_KING:BLACK_KING) &&
( board->board[dx][dy]!=WHITE_KING && board->board[dx][dy]!=BLACK_KING ))
{
board->board[dx][dy] = destpiece;
board->board[x][y] = piece;
}
else
{
board->turn++;
imc_send_chess((CHAR_DATA *)board->player1?:NULL,(char *)from->name, "moveok");
return;
}
}
imc_send_chess((CHAR_DATA *)victim->pcdata->game_board->player1?:NULL,(char *)from->name, "invalidmove");
return;
}
sprintf(log_buf, "Unknown chess command from: %s, %s", from->name, argument);
log_string(log_buf);
}
#endif
void do_game_board(CHAR_DATA *ch, char *argument, int cmdnumber)
{
char arg[MAX_INPUT_LENGTH];
argument = one_argument(argument, arg);
if ( IS_NPC(ch) )
{
send_to_char("NPC's can't be in games.\n\r", ch);
return;
}
if ( !str_cmp(arg, "begin") )
{
GAME_BOARD_DATA *board;
if ( ch->pcdata->game_board )
{
send_to_char("You are already in a chess match.\n\r", ch);
return;
}
CREATE(board, GAME_BOARD_DATA, 1);
init_board(board);
ch->pcdata->game_board = board;
ch->pcdata->game_board->player1 = ch;
send_to_char("You have started a game of chess.\n\r", ch);
return;
}
if ( !str_cmp(arg, "join") )
{
GAME_BOARD_DATA *board=NULL;
CHAR_DATA *vch;
char arg2[MAX_INPUT_LENGTH];
if ( ch->pcdata->game_board )
{
send_to_char("You are already in a game of chess.\n\r", ch);
return;
}
argument = one_argument(argument,arg2);
if ( arg[0] == '\0' )
{
send_to_char("Join whom in a chess match?\n\r", ch);
return;
}
#ifdef USE_IMC
if ( strstr( arg2, "@" ) )
{
if (!str_cmp(imc_mudof(arg2), imc_name))
{
send_to_char("That is this mud, don't use @.\n\r",ch);
return;
}
send_to_char("Attempting to initiate IMC game...\n\r", ch);
if (!str_cmp(imc_mudof(arg2), "*"))
{
send_to_char("* is not a valid mud name.\n\r",ch);
return;
}
CREATE(board, GAME_BOARD_DATA, 1);
init_board(board);
board->type = TYPE_IMC;
board->player1 = (void *)ch;
board->player2 = (void *)str_dup(arg2);
board->turn = -1;
ch->pcdata->game_board = board;
imc_send_chess(ch,arg2,"start");
return;
}
#endif
if ( !( vch = get_char_world(ch,arg2) ) )
{
send_to_char("Cannot find that player.\n\r", ch);
return;
}
if ( IS_NPC(vch) )
{
send_to_char("That player is an NPC, and cannot play games.\n\r", ch);
return;
}
board = vch->pcdata->game_board;
if ( !board )
{
send_to_char("That player is not playing a game.\n\r", ch);
return;
}
if ( board->player2 )
{
send_to_char("That game already has two players.\n\r", ch);
return;
}
board->player2 = (void *)ch;
ch->pcdata->game_board = board;
send_to_char("You have joined a game of chess.\n\r", ch);
ch_printf((CHAR_DATA *)board->player1, "%s has joined your game.\n\r", GET_NAME(ch));
return;
}
if ( !ch->pcdata->game_board )
{
send_to_char("Usage: chess <begin|cease|status|board|move|join>\n\r",ch);
return;
}
if ( !str_cmp(arg, "cease") )
{
free_game(ch->pcdata->game_board);
return;
}
if ( !str_cmp(arg, "status") )
{
GAME_BOARD_DATA *board = ch->pcdata->game_board;
if ( !board->player1 )
send_to_char("There is no black player.\n\r", ch);
else if ( board->player1 == ch )
send_to_char("You are black.\n\r", ch);
else
ch_printf(ch, "%s is black.\n\r",
GET_NAME((CHAR_DATA *)board->player1));
if (king_in_checkmate(board,BLACK_KING))
send_to_char("The black king is in check.\n\r", ch);
else if (king_in_check(board,BLACK_KING))
send_to_char("The black king is in check.\n\r", ch);
if ( !board->player2 )
send_to_char("There is no white player.\n\r", ch);
else if ( board->player2 == ch )
send_to_char("You are white.\n\r", ch);
else
ch_printf(ch, "%s is white.\n\r",
board->type == TYPE_LOCAL ?
GET_NAME((CHAR_DATA *)board->player2) :
(char *)board->player2);
if (king_in_checkmate(board,WHITE_KING))
send_to_char("The white king is in check.\n\r", ch);
else if (king_in_check(board,WHITE_KING))
send_to_char("The white king is in check.\n\r", ch);
if ( !board->player2 ||
!board->player1 )
return;
ch_printf(ch, "%d turns.\n\r", board->turn);
if ( board->turn % 2 == 1 && board->player1 == ch )
{
ch_printf(ch, "It is %s's turn.\n\r", GET_NAME((CHAR_DATA *)board->player2));
return;
}
else if ( board->turn % 2 == 0 && board->player2 == ch )
{
ch_printf(ch, "It is %s's turn.\n\r",
board->type == TYPE_LOCAL ?
GET_NAME((CHAR_DATA *)board->player1) :
(char *)board->player1);
return;
}
else
{
send_to_char("It is your turn.\n\r", ch);
return;
}
return;
}
if ( !str_prefix(arg, "board") )
{
static char *b1;
b1 = print_big_board(ch, ch->pcdata->game_board);
send_to_char(b1,ch);
return;
}
if ( !str_prefix(arg, "move") )
{
CHAR_DATA *opp;
char a,b;
int x,y,dx,dy,ret;
if ( !ch->pcdata->game_board->player1 ||
!ch->pcdata->game_board->player2 )
{
send_to_char("There is only 1 player.\n\r", ch);
return;
}
if ( ch->pcdata->game_board->turn < 0 )
{
send_to_char("The game hasn't started yet.\n\r", ch);
return;
}
if ( king_in_checkmate(ch->pcdata->game_board, BLACK_KING) )
{
send_to_char("The black king has been checkmated, the game is over.\n\r", ch);
return;
}
if ( king_in_checkmate(ch->pcdata->game_board, WHITE_KING) )
{
send_to_char("The white king has been checkmated, the game is over.\n\r", ch);
return;
}
if ( !*argument )
{
send_to_char("Usage: chess move [piece to move] [where to move]\n\r",ch);
return;
}
if ( ch->pcdata->game_board->turn % 2 == 1 &&
ch->pcdata->game_board->player1 == ch )
{
send_to_char("It is not your turn.\n\r", ch);
return;
}
if ( ch->pcdata->game_board->turn % 2 == 0 &&
ch->pcdata->game_board->player2 == ch )
{
send_to_char("It is not your turn.\n\r", ch);
return;
}
if (sscanf(argument,"%c%d %c%d",&a,&y,&b,&dy)!=4)
{
send_to_char("Usage: chess move [dest] [source]\n\r",ch);
return;
}
if ( a < 'a' || a > 'h' || b < 'a' || b > 'h' || y < 1 || y > 8 || dy < 1 || dy > 8 )
{
send_to_char("Invalid move, use a-h, 1-8.\n\r", ch);
return;
}
x = a - 'a';
dx = b - 'a';
y--;
dy--;
ret = is_valid_move(ch,ch->pcdata->game_board,x,y,dx,dy);
if (ret == MOVE_OK || ret == MOVE_TAKEN)
{
GAME_BOARD_DATA *board;
int piece, destpiece;
board = ch->pcdata->game_board;
piece = board->board[x][y];
destpiece = board->board[dx][dy];
board->board[dx][dy] = piece;
board->board[x][y] = NO_PIECE;
if ( king_in_check(board,IS_WHITE(board->board[dx][dy])?WHITE_KING:BLACK_KING) &&
( board->board[dx][dy]!=WHITE_KING && board->board[dx][dy]!=BLACK_KING ))
{
board->board[dx][dy] = destpiece;
board->board[x][y] = piece;
ret = MOVE_INCHECK;
}
else
{
board->turn++;
#ifdef USE_IMC
if ( ch->pcdata->game_board->type == TYPE_IMC)
{
sprintf(arg, "move %d%d %d%d", x, y, dx, dy);
imc_send_chess((CHAR_DATA *)ch->pcdata->game_board->player1, (char *)ch->pcdata->game_board->player2, arg);
}
#endif
}
}
if ( ch == ch->pcdata->game_board->player1 )
opp = (CHAR_DATA *)ch->pcdata->game_board->player2;
else
opp = (CHAR_DATA *)ch->pcdata->game_board->player1;
#ifdef USE_IMC
#define SEND_TO_OPP(arg,opp) \
if (opp) \
{ \
if (ch->pcdata->game_board->type==TYPE_LOCAL) \
send_to_char((arg),(opp)); \
if (ch->pcdata->game_board->type==TYPE_IMC) \
imc_send_tell(NULL, (char *)(opp), (arg), 1); \
}
#else
#define SEND_TO_OPP(arg,opp) \
if (opp) \
{ \
if (ch->pcdata->game_board->type==TYPE_LOCAL) \
send_to_char((arg),(opp)); \
}
#endif
switch (ret)
{
case MOVE_OK:
send_to_char("Ok.\n\r", ch);
sprintf(arg, "%s has moved.\n\r", GET_NAME(ch));
SEND_TO_OPP(arg, opp);
break;
case MOVE_INVALID:
send_to_char("Invalid move.\n\r", ch);
break;
case MOVE_BLOCKED:
send_to_char("You are blocked in that direction.\n\r", ch);
break;
case MOVE_TAKEN:
send_to_char("You take the enemy's piece.\n\r", ch);
sprintf(arg, "%s has taken one of your pieces!", GET_NAME(ch));
SEND_TO_OPP(arg, opp);
break;
case MOVE_CHECKMATE:
send_to_char("That move would result in a checkmate.\n\r", ch);
sprintf(arg, "%s has attempted a move that would result in checkmate.", GET_NAME(ch));
SEND_TO_OPP(arg, opp);
break;
case MOVE_OFFBOARD:
send_to_char("That move would be off the board.\n\r", ch);
break;
case MOVE_SAMECOLOR:
send_to_char("Your own piece blocks the way.\n\r", ch);
break;
case MOVE_CHECK:
send_to_char("That move would result in a check.\n\r", ch);
sprintf(arg, "%s has made a move that would result in a check.", GET_NAME(ch));
SEND_TO_OPP(arg, opp);
break;
case MOVE_WRONGCOLOR:
send_to_char("That is not your piece.\n\r", ch);
break;
case MOVE_INCHECK:
send_to_char("You are in check, you must save your king.\n\r", ch);
break;
default:
bug("Unknown return value from is_valid_move():games.c");
break;
}
#undef SEND_TO_OPP
return;
}
send_to_char("Usage: chess <begin|cease|status|board|move|join>\n\r",ch);
}