Esempio n. 1
1
bool
apply_move (Game *g, int from, int to, char promote_in)
{
  if (g->result != IN_PROGRESS) return FALSE;
  Board *board = current_board (g);
  Board *new_board = NEW_BOARD;
  char capture = 0;
  char *move_done = castling (board, castling_type (board, from, to), new_board);
  if (!move_done) // If move is not a castling
    {
      if (!try_move (board, from, to, promote_in, new_board, &move_done, &capture))
        {
          free (new_board);
          return FALSE;
        }
    }
  // Ok move is legal, update the game
  update_castling (new_board, from);
  update_en_passant (new_board, from, to);
  if (new_board->active_color)
    new_board->fullmove_number++;
  new_board->active_color = !new_board->active_color;
  if (capture || toupper (board->placement[from]) == 'P')
    new_board->halfmove_clock = 0;
  else
    new_board->halfmove_clock++;
  g->boards[g->current] = new_board;
  g->moves[g->current] = move_done;
  g->coord_moves[g->current] = ft_to_coord_move (from, to, promote_in);
  g->current++;
  // Test check or checkmate of opponent king
  if (king_in_check (new_board, new_board->active_color))
    {
      if (king_in_checkmate (new_board, new_board->active_color))
        {
          strcat (move_done, "#");
          g->result = !new_board->active_color;
        }
      else
        strcat (move_done, "+");
    }
  // Test insufficient material
  else if (insufficient_material (new_board))
    g->result = DRAW;
  // Test stalemate
  else if (stalemate (new_board, new_board->active_color))
    g->result = DRAW;
  return TRUE;
}
Esempio n. 2
0
void do_chess( CHAR_DATA * ch, const char *argument )
{
	char arg[MAX_INPUT_LENGTH];

	argument = one_argument( argument, arg );

	if ( IS_NPC( ch ) )
	{
		send_to_char( "NPC's can't be in chess games.\r\n", 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.\r\n", ch );
			return;
		}

		CREATE( board, GAME_BOARD_DATA, 1 );
		init_board( board );
		ch->pcdata->game_board = board;
		ch->pcdata->game_board->player1 = QUICKLINK( ch->name );
		send_to_char( "You have started a game of chess.\r\n", 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.\r\n", ch );
			return;
		}

		argument = one_argument( argument, arg2 );
		if ( arg2[0] == '\0' )
		{
			send_to_char( "Join whom in a chess match?\r\n", ch );
			return;
		}

#ifdef IMC
		if ( strstr( arg2, "@" ) )
		{
			if ( !str_cmp( imc_mudof( arg2 ), this_imcmud->localname ) )
			{
				send_to_char( "You cannot join IMC chess on the local mud!\r\n", ch );
				return;
			}

			if ( !str_cmp( imc_mudof( arg2 ), "*" ) )
			{
				send_to_char( "* is not a valid mud name.\r\n", ch );
				return;
			}

			if ( !str_cmp( imc_nameof( arg2 ), "*" ) )
			{
				send_to_char( "* is not a valid player name.\r\n", ch );
				return;
			}

			send_to_char( "Attempting to initiate IMC chess game...\r\n", ch );

			CREATE( board, GAME_BOARD_DATA, 1 );
			init_board( board );
			board->type = TYPE_IMC;
			board->player1 = QUICKLINK( ch->name );
			board->player2 = STRALLOC( arg2 );
			board->turn = -1;
			ch->pcdata->game_board = board;
			imc_send_chess( ch->name, arg2, "start" );
			return;
		}
#endif

		if ( !( vch = get_char_world( ch, arg2 ) ) )
		{
			send_to_char( "Cannot find that player.\r\n", ch );
			return;
		}

		if ( IS_NPC( vch ) )
		{
			send_to_char( "That player is an NPC, and cannot play games.\r\n", ch );
			return;
		}

		board = vch->pcdata->game_board;
		if ( !board )
		{
			send_to_char( "That player is not playing a game.\r\n", ch );
			return;
		}

		if ( board->player2 )
		{
			send_to_char( "That game already has two players.\r\n", ch );
			return;
		}

		board->player2 = QUICKLINK( ch->name );
		ch->pcdata->game_board = board;
		send_to_char( "You have joined a game of chess.\r\n", ch );

		vch = get_char_world( ch, board->player1 );
		ch_printf( vch, "%s has joined your game.\r\n", ch->name );
		return;
	}

	if ( !ch->pcdata->game_board )
	{
		send_to_char( "Usage: chess <begin|cease|status|board|move|join>\r\n", 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.\r\n", ch );
		else if ( !str_cmp( board->player1, ch->name ) )
			send_to_char( "You are black.\r\n", ch );
		else
			ch_printf( ch, "%s is black.\r\n", board->player1 );

		if ( king_in_checkmate( board, BLACK_KING ) )
			send_to_char( "The black king is in checkmate!\r\n", ch );
		else if ( king_in_check( board, BLACK_KING ) )
			send_to_char( "The black king is in check.\r\n", ch );

		if ( !board->player2 )
			send_to_char( "There is no white player.\r\n", ch );
		else if ( !str_cmp( board->player2, ch->name ) )
			send_to_char( "You are white.\r\n", ch );
		else
			ch_printf( ch, "%s is white.\r\n", board->player2 );

		if ( king_in_checkmate( board, WHITE_KING ) )
			send_to_char( "The white king is in checkmate!\r\n", ch );
		else if ( king_in_check( board, WHITE_KING ) )
			send_to_char( "The white king is in check.\r\n", ch );

		if ( !board->player2 || !board->player1 )
			return;

		ch_printf( ch, "%d turns.\r\n", board->turn );
		if ( board->turn % 2 == 1 && !str_cmp( board->player1, ch->name ) )
		{
			ch_printf( ch, "It is %s's turn.\r\n", board->player2 );
			return;
		}
		else if ( board->turn % 2 == 0 && !str_cmp( board->player2, ch->name ) )
		{
			ch_printf( ch, "It is %s's turn.\r\n", board->player1 );
			return;
		}
		else
		{
			send_to_char( "It is your turn.\r\n", ch );
			return;
		}
		return;
	}

	if ( !str_prefix( arg, "board" ) )
	{
		send_to_char( print_big_board( ch, ch->pcdata->game_board ), ch );
		return;
	}

	if ( !str_prefix( arg, "move" ) )
	{
		CHAR_DATA *opp;
		char opp_name[MAX_INPUT_LENGTH];
		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.\r\n", ch );
			return;
		}

		if ( ch->pcdata->game_board->turn < 0 )
		{
			send_to_char( "The game hasn't started yet.\r\n", 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.\r\n", 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.\r\n", ch );
			return;
		}

		if ( !*argument )
		{
			send_to_char( "Usage: chess move [piece to move] [where to move]\r\n", ch );
			return;
		}

		if ( ch->pcdata->game_board->turn % 2 == 1 && !str_cmp( ch->pcdata->game_board->player1, ch->name ) )
		{
			send_to_char( "It is not your turn.\r\n", ch );
			return;
		}

		if ( ch->pcdata->game_board->turn % 2 == 0 && !str_cmp( ch->pcdata->game_board->player2, ch->name ) )
		{
			send_to_char( "It is not your turn.\r\n", ch );
			return;
		}

		if ( sscanf( argument, "%c%d %c%d", &a, &y, &b, &dy ) != 4 )
		{
			send_to_char( "Usage: chess move [dest] [source]\r\n", 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.\r\n", 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 IMC
				if ( ch->pcdata->game_board->type == TYPE_IMC )
				{
					snprintf( arg, LGST, "move %d%d %d%d", x, y, dx, dy );
					imc_send_chess( ch->pcdata->game_board->player1, ch->pcdata->game_board->player2, arg );
				}
#endif
			}
		}

		if ( !str_cmp( ch->name, ch->pcdata->game_board->player1 ) )
		{
			opp = get_char_world( ch, ch->pcdata->game_board->player2 );
			if ( !opp )
				mudstrlcpy( opp_name, ch->pcdata->game_board->player2, MAX_INPUT_LENGTH );
		}
		else
		{
			opp = get_char_world( ch, ch->pcdata->game_board->player1 );
			if ( !opp )
				mudstrlcpy( opp_name, ch->pcdata->game_board->player1, MAX_INPUT_LENGTH );
		}

#ifdef IMC
#    define SEND_TO_OPP(arg,opp) \
      if( opp ) \
      { \
         if( ch->pcdata->game_board->type == TYPE_LOCAL ) \
            ch_printf( (opp), "%s\r\n", (arg) ); \
      } \
      else \
      { \
         if( ch->pcdata->game_board->type == TYPE_IMC ) \
            imc_send_tell( ch->name, opp_name, (arg), 1 ); \
      }
#else
#    define SEND_TO_OPP(arg,opp) \
      if( opp ) \
      { \
         if( ch->pcdata->game_board->type == TYPE_LOCAL ) \
            ch_printf( (opp), "%s\r\n", (arg) ); \
      }
#endif

		switch ( ret )
		{
			case MOVE_OK:
				send_to_char( "Ok.\r\n", ch );
				snprintf( arg, MAX_INPUT_LENGTH, "%s has moved.\r\n", ch->name );
				SEND_TO_OPP( arg, opp );
				break;

			case MOVE_INVALID:
				send_to_char( "Invalid move.\r\n", ch );
				break;

			case MOVE_BLOCKED:
				send_to_char( "You are blocked in that direction.\r\n", ch );
				break;

			case MOVE_TAKEN:
				send_to_char( "You take the enemy's piece.\r\n", ch );
				snprintf( arg, MAX_INPUT_LENGTH, "%s has taken one of your pieces!", ch->name );
				SEND_TO_OPP( arg, opp );
				break;

			case MOVE_CHECKMATE:
				send_to_char( "That move would result in a checkmate.\r\n", ch );
				snprintf( arg, MAX_INPUT_LENGTH, "%s has attempted a move that would result in checkmate.", ch->name );
				SEND_TO_OPP( arg, opp );
				break;

			case MOVE_OFFBOARD:
				send_to_char( "That move would be off the board.\r\n", ch );
				break;

			case MOVE_SAMECOLOR:
				send_to_char( "Your own piece blocks the way.\r\n", ch );
				break;

			case MOVE_CHECK:
				send_to_char( "That move would result in a check.\r\n", ch );
				snprintf( arg, MAX_INPUT_LENGTH, "%s has made a move that would result in a check.", ch->name );
				SEND_TO_OPP( arg, opp );
				break;

			case MOVE_WRONGCOLOR:
				send_to_char( "That is not your piece.\r\n", ch );
				break;

			case MOVE_INCHECK:
				send_to_char( "You are in check, you must save your king.\r\n", ch );
				break;

			default:
				bug( "%s: Unknown return value", __FUNCTION__ );
				break;
		}
#undef SEND_TO_OPP
		return;
	}
	send_to_char( "Usage: chess <begin|cease|status|board|move|join>\r\n", ch );
}
Esempio n. 3
0
/*
 A FEN string is composed of 6 parts separated by " " (space).
 1. Piece placement (from white's perspective).
 2. Active color. "w" means white moves next, "b" means black.
 3. Castling availability. If neither side can castle, this is "-".
 4. En passant target square in algebraic notation. If there's no en passant target square, this is "-".
 5. Halfmove clock: this is the number of halfmoves since the last pawn advance or capture.
 6. Fullmove number: the number of the full move. It starts at 1, and is incremented after black's move.
*/
void
set_fen (Game *g, const char *fen)
{
  Board *board = NEW_BOARD;
  int i = 0, j, k, square;
  char *pch;
  char *s = (char *) malloc (sizeof (char) * (strlen (fen) + 1));
  strcpy (s, fen);
  // Init board
  memset (board->placement, '\0', 64);
  board->pawns[WHITE]   = 0x0;
  board->pawns[BLACK]   = 0x0;
  board->rooks[WHITE]   = 0x0;
  board->rooks[BLACK]   = 0x0;
  board->knights[WHITE] = 0x0;
  board->knights[BLACK] = 0x0;
  board->bishops[WHITE] = 0x0;
  board->bishops[BLACK] = 0x0;
  board->queens[WHITE]  = 0x0;
  board->queens[BLACK]  = 0x0;
  board->king[WHITE]    = 0x0;
  board->king[BLACK]    = 0x0;
  pch = strtok (s, " /");
  while (pch != NULL)
    {
      if (i < 8)
        {
          for (j = 0, k = 0; j < (int) strlen (pch); j++)
            {
              if (pch[j] - 48 > 8)
                {
                  square = (abs (i - 7) * 8) + k;
                  switch (pch[j])
                    {
                      case 'P':
                      board->placement[square] = pch[j];
                      board->pawns[WHITE] ^= 1ULL << square;
                      break;
                      case 'p':
                      board->placement[square] = pch[j];
                      board->pawns[BLACK] ^= 1ULL << square;
                      break;
                      case 'R':
                      board->placement[square] = pch[j];
                      board->rooks[WHITE] ^= 1ULL << square;
                      break;
                      case 'r':
                      board->placement[square] = pch[j];
                      board->rooks[BLACK] ^= 1ULL << square;
                      break;
                      case 'N':
                      board->placement[square] = pch[j];
                      board->knights[WHITE] ^= 1ULL << square;
                      break;
                      case 'n':
                      board->placement[square] = pch[j];
                      board->knights[BLACK] ^= 1ULL << square;
                      break;
                      case 'B':
                      board->placement[square] = pch[j];
                      board->bishops[WHITE] ^= 1ULL << square;
                      break;
                      case 'b':
                      board->placement[square] = pch[j];
                      board->bishops[BLACK] ^= 1ULL << square;
                      break;
                      case 'Q':
                      board->placement[square] = pch[j];
                      board->queens[WHITE] ^= 1ULL << square;
                      break;
                      case 'q':
                      board->placement[square] = pch[j];
                      board->queens[BLACK] ^= 1ULL << square;
                      break;
                      case 'K':
                      board->placement[square] = pch[j];
                      board->king[WHITE] ^= 1ULL << square;
                      break;
                      case 'k':
                      board->placement[square] = pch[j];
                      board->king[BLACK] ^= 1ULL << square;
                      break;
                    }
                  k++;
                }
              else
                k += pch[j] - 48;
            }
        }
      else if (i == 8)
        {
          board->active_color = pch[0] == 'b';
        }
      else if (i == 9)
        {
          board->castling = 0x0000;
          for (j = 0; j < (int) strlen (pch); j++)
            {
              switch (pch[j])
                {
                  case 'K':
                  board->castling |= 0x1000;
                  break;
                  case 'Q':
                  board->castling |= 0x0100;
                  break;
                  case 'k':
                  board->castling |= 0x0010;
                  break;
                  case 'q':
                  board->castling |= 0x0001;
                  break;
                }
            }
        }
      else if (i == 10)
        {
          board->en_passant = coord_to_square (pch);
        }
      else if (i == 11)
        {
          board->halfmove_clock = atoi (pch);
        }
      else if (i == 12)
        {
          board->fullmove_number = atoi (pch);
        }
      i++;
      pch = strtok (NULL, " /");
    }
  set_occupied (board);
  g->boards[g->current] = board;
  g->moves[g->current] = (char *) malloc (11);
  g->coord_moves[g->current] = (char *) malloc (11);
  strcpy (g->moves[g->current], "SET BY FEN");
  strcpy (g->coord_moves[g->current], "SET BY FEN");
  g->current++;

  // check result
  if (king_in_checkmate (board, board->active_color))
    g->result = !board->active_color;
  else
    if (stalemate (board, board->active_color) || insufficient_material (board))
      g->result = DRAW;

  free (s);
}