Ejemplo 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;
}
Ejemplo n.º 2
0
/*
 * stampa al pg il suo stato attuale di gioco
 */
void show_status( CHAR_DATA *ch, CHESSBOARD_DATA *board )
{
	if ( !ch )
	{
		send_log( NULL, LOG_BUG, "print_status: ch passato è NULL" );
		return;
	}

	if ( !board )
	{
		send_to_char( ch, "Non sto giocando a nessuna partita di scacchi.\r\n" );
		return;
	}

	if ( !board->player1 )
		send_to_char( ch, "Non ho nessun giocatore per i pezzi neri con cui gareggiare.\r\n" );
	else if ( board->player1 == ch )
		send_to_char( ch, "Sono io il giocatore dei pezzi neri.\r\n" );
	else
		ch_printf( ch, "%s è il giocatore che tiene i pezzi neri.\r\n", board->player1->name );

	if ( king_in_possible_checkmate(board, PIECE_KING, COLOR_BLACK) )
		send_to_char( ch, "Il re nero potrebbe essere sotto scacco matto.\r\n" );
	else if ( king_in_check(board, PIECE_KING, COLOR_BLACK) > 0 )
		send_to_char( ch, "Il re nero è sotto scacco.\r\n" );

	if ( !board->player2 )
		send_to_char( ch, "Non ho nessun giocatore per i pezzi bianchi con cui gareggiare.\r\n" );
	else if ( board->player2 == ch )
		send_to_char( ch, "Sono io il giocatore dei pezzi bianchi.\r\n" );
	else
		ch_printf( ch, "%s è il giocatore che tiene i pezzi bianchi.\r\n", board->player2->name );

	if ( king_in_possible_checkmate(board, PIECE_KING, COLOR_WHITE) )
		send_to_char( ch, "Il re bianco potrebbe essere sotto scacco matto.\r\n" );
	else if ( king_in_check(board, PIECE_KING, COLOR_WHITE) > 0 )
		send_to_char( ch, "Il re bianco è sotto scacco.\r\n" );

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

	if ( board->moves < 0 )
		send_to_char( ch, "Il gioco non è ancora iniziato.\r\n" );
	else
		ch_printf( ch, "%d turni.\r\n", board->moves );

	if ( board->turn == ch )
		send_to_char( ch, "E' il mio turno.\r\n" );
	else
		ch_printf( ch, "E' il turno di %s.\r\n", board->turn->name );
}
Ejemplo n.º 3
0
Archivo: move.c Proyecto: jes/zoe
/* return 1 if the move is valid and 0 otherwise, printing an appropriate
 * message if print is non-zero.
 */
int is_valid_move(Game game, Move m, int print) {
    Board *board = &(game.board);
    Game game2 = game;
    uint64_t beginbit, endbit;
    char *strmove = xboard_move(m);

    beginbit = 1ull << m.begin;
    endbit = 1ull << m.end;

    /* ensure that the piece belongs to the current player */
    if(!(board->b[game.turn][OCCUPIED] & beginbit)) {
        if(print)
            printf("Illegal move (%s): that is not your piece.\n", strmove);
        return 0;
    }

    /* ensure that the end tile can be moved to from the begin tile */
    if(!(generate_moves(&game, m.begin) & endbit)) {
        if(print)
            printf("Illegal move (%s): that piece can't move like that.\n",
                    strmove);
        return 0;
    }

    /* ensure that pawns reaching the eighth rank promote */
    if(!m.promote && ((m.end / 8) == 0 || (m.end / 8) == 7)
            && board->mailbox[m.begin] == PAWN) {
        if(print)
            printf("Illegal move (%s): pawns reaching the eighth rank must "
                    "promote.\n", strmove);
        return 0;
    }

    /* ensure that no other pieces promote */
    if(m.promote && (board->mailbox[m.begin] != PAWN
                || ((m.end / 8) != 0 && (m.end / 8) != 7))) {
        if(print)
            printf("Illegal move (%s): that piece may not promote at this "
                    "time.\n", strmove);
        return 0;
    }

    /* ensure that the king is not left in check
     * NOTE: we apply_move() here, so the state of the game is changed; this
     * check must be done last
     */
    apply_move(&game2, m);
    if(king_in_check(&(game2.board), game.turn)) {
        if(print)
            printf("Illegal move (%s): king is left in check.\n", strmove);
        return 0;
    }

    /* hasn't failed any validation, must be a valid move */
    return 1;
}
Ejemplo n.º 4
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 );
}
Ejemplo n.º 5
0
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] ) && !str_cmp( board->player1, ch->name ) )
		return MOVE_WRONGCOLOR;
	if ( IS_BLACK( board->board[x][y] ) && ( !str_cmp( board->player2, ch->name ) || !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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
int is_valid_move( char_data * ch, game_board_data * board, int x, int y, int dx, int dy )
{
    if( !ch )
    {
        bug( "%s: nullptr ch!", __func__ );
        return MOVE_INVALID;
    }

    if( !board )
    {
        bug( "%s: nullptr board!", __func__ );
        return MOVE_INVALID;
    }

    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] ) && !str_cmp( board->player1, ch->name ) )
        return MOVE_WRONGCOLOR;
    if( IS_BLACK( board->board[x][y] ) && ( !ch || !str_cmp( board->player2, ch->name ) ) )
        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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
/*
 * Controlla e ritorna il tipo di mossa effettuata
 */
int is_valid_move( CHAR_DATA *ch, CHESSBOARD_DATA *board, int x, int y, int dx, int dy )
{
	if ( !ch )
	{
		send_log( NULL, LOG_BUG, "is_valid_move: ch è NULL" );
		return MOVE_INVALID;
	}

	if ( !board )
	{
		send_log( NULL, LOG_BUG, "is_valid_move: board è NULL" );
		return MOVE_INVALID;
	}

	if ( x < 0 || y < 0 || x >= 8 || y >= 8 )
	{
		send_log( NULL, LOG_BUG, "is_valid_move: coordinate passate errate: x=%d y =%d", x, y );
		return MOVE_INVALID;
	}

	if ( dx < 0 || dy < 0 || dx >= 8 || dy >= 8 )
	{
		send_log( NULL, LOG_BUG, "is_valid_move: coordinate passate errate: dx=%d dy =%d", dx, dy );
		return MOVE_OFFBOARD;
	}

	if ( board->piece[x][y] == PIECE_NONE )
	{
		send_to_char( ch, "Non trovo nessun pezzo in quella casella.\r\n" );
		return MOVE_INVALID;
	}

	if ( x == dx && y == dy )
	{
		send_to_char( ch, "La sorgente e l'arrivo della mossa sono identiche.\r\n" );
		return MOVE_INVALID;
	}

	if ( (board->color[x][y] == COLOR_WHITE && ch == board->player1)
	  || (board->color[x][y] == COLOR_BLACK && ch == board->player2) )
	{
		send_to_char( ch, "Sto cercando di muovere un pezzo che non è del mio colore.\r\n" );
		return MOVE_WRONGCOLOR;
	}

	switch ( board->piece[x][y] )
	{
	  default:
		send_log( NULL, LOG_BUG, "is_valid_move():chess.c invaild piece: %d", board->piece[x][y] );
		send_to_char( ch, "-> Mossa sbagliata, avverti i Coder <-" );
		return MOVE_INVALID;
		break;

	  case PIECE_PAWN:
		if ( board->color[x][y] == COLOR_WHITE && dx == x+2 && x == 1 && dy == y
		  && board->piece[dx][dy] == PIECE_NONE && board->piece[x+1][dy] == PIECE_NONE )
			return MOVE_OK;
		if ( board->color[x][y] == COLOR_BLACK && dx == x-2 && x == 6 && dy == y
		  && board->piece[dx][dy] == PIECE_NONE && board->piece[x-1][dy] == PIECE_NONE )
			return MOVE_OK;

		if ( (board->color[x][y] == COLOR_WHITE && dx != x+1)
		  || (board->color[x][y] == COLOR_BLACK && dx != x-1) )
		{
			send_to_char( ch, "Debbo muovere il pedone di un passo per volta, solo dalle caselle di partenza del pedone è consentito una mossa da 2.\r\n" );
			return MOVE_INVALID;
		}

		if ( dy != y && dy != y-1 && dy != y+1 )
		{
			send_to_char( ch, "Debbo muovere il pedone sempre in avanti, oppure in diagonale di una casella quando può fare gambetto.\r\n" );
			return MOVE_INVALID;
		}

		if ( dy == y )
		{
			if ( board->piece[dx][dy] == PIECE_NONE )
				return MOVE_OK;
			if ( SAME_COLOR(x, y, dx, dy) )
			{
				send_to_char( ch, "Non posso muovere dove c'è un'altro pezzo del mio stesso colore.\r\n" );
				return MOVE_SAMECOLOR;
			}

			send_to_char( ch, "Non posso eseguire questa mossa.\r\n" );
			return MOVE_BLOCKED;
		}
		else
		{
			if ( board->piece[dx][dy] == PIECE_NONE )
			{
				/* (FF) (bb) Bisognerebbe gestire anche il gambetto */
				send_to_char( ch, "Non c'è nessun pezzo da mangiare in quella casella.\r\n" );
				return MOVE_INVALID;
			}
			if ( SAME_COLOR(x, y, dx, dy) )
			{
				send_to_char( ch, "Non posso mangiare un pezzo del mio stesso colore.\r\n" );
				return MOVE_SAMECOLOR;
			}
			if ( board->piece[dx][dy] != PIECE_KING )
				return MOVE_TAKEN;

			send_to_char( ch, "Non posso fare questa mossa.\r\n" );
			return MOVE_INVALID;
		}
		break;

	  case PIECE_ROOK:
	  {
		int cnt;

		if ( dx != x && dy != y )
		{
			send_to_char( ch, "Devo muovere la torre verticalmente o orizzontalmente dalla propria posizione.\r\n" );
			return MOVE_INVALID;
		}

		if ( dx == x )
		{
			for ( cnt = y;  cnt != dy; )
			{
				if ( cnt != y && board->piece[x][cnt] != PIECE_NONE )
				{
					send_to_char( ch, "Non posso spostare la torre fino a lì, qualche pezzo blocca la strada" );
					return MOVE_BLOCKED;
				}
				if ( dy > y )
					cnt++;
				else
					cnt--;
			}
		}
		else if ( dy == y )
		{
			for ( cnt = x;  cnt != dx; )
			{
				if ( cnt != x && board->piece[cnt][y] != PIECE_NONE )
				{
					send_to_char( ch, "Non posso spostare la torre fino a lì, qualche pezzo blocca la strada" );
					return MOVE_BLOCKED;
				}
				if ( dx > x )
					cnt++;
				else
					cnt--;
			}
		}

		if ( board->piece[dx][dy] == PIECE_NONE )
			return MOVE_OK;

		if ( SAME_COLOR(x, y, dx, dy) )
		{
			send_to_char( ch, "Non posso mangiare un pezzo del mio stesso colore.\r\n" );
			return MOVE_SAMECOLOR;
		}

		return MOVE_TAKEN;
	  }
	  break;

	  case PIECE_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->piece[dx][dy] == PIECE_NONE )
				return MOVE_OK;
			if ( SAME_COLOR(x, y, dx, dy) )
			{
				send_to_char( ch, "Non posso mangiare un pezzo del mio stesso colore.\r\n" );
				return MOVE_SAMECOLOR;
			}

			return MOVE_TAKEN;
		}
		send_to_char( ch, "Devo posso muovere il mio cavallo così.\r\n" );
		return MOVE_INVALID;
		break;

	  case PIECE_BISHOP:
	  {
		int	l;
		int	m;
		int	blocked = FALSE;

		if ( dx == x || dy == y )
		{
			send_to_char( ch, "Devo muovere l'alfiere diagonalmente dalla sua posizione.\r\n" );
			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 )
			{
				send_to_char( ch, "Non posso uscire dalla scacchiera.\r\n" );
				return MOVE_INVALID;
			}
			if ( l == dx && m == dy )
				break;

			if ( board->piece[l][m] != PIECE_NONE )
				blocked = TRUE;
		}

		if ( l != dx || m != dy )
		{
			send_to_char( ch, "Devo muovere l'alfiere diagonalmente dalla sua posizione.\r\n" );
			return MOVE_INVALID;
		}

		if ( blocked )
		{
			send_to_char( ch, "Non posso spostare il mio alfiere lì, qualche pezzo blocca la strada" );
			return MOVE_BLOCKED;
		}

		if ( board->piece[dx][dy] == PIECE_NONE )
			return MOVE_OK;

		if ( SAME_COLOR(x, y, dx, dy) )
		{
			send_to_char( ch, "Non posso mangaire un pezzo del mio stesso colore.\r\n" );
			return MOVE_SAMECOLOR;
		}

		return MOVE_TAKEN;
	  }
	  break;

	  case PIECE_QUEEN:
	  {
		int l;
		int m;
		int 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 )
			{
				send_to_char( ch, "Non posso muovere fuori dalla scacchiera.\r\n" );
				return MOVE_INVALID;
			}
			if ( l == dx && m == dy )
				break;

			if ( board->piece[l][m] != PIECE_NONE )
				blocked = TRUE;
		}

		if ( l != dx || m != dy )
		{
			send_to_char( ch, "Devo muovere la regina orizzonalmente, verticalmente o in diagonale dalla sua posizione.\r\n" );
			return MOVE_INVALID;
		}

		if ( blocked )
		{
			send_to_char( ch, "Non posso spostare la mia regina lì, qualche pezzo blocca la strada" );
			return MOVE_BLOCKED;
		}

		if ( board->piece[dx][dy] == PIECE_NONE )
			return MOVE_OK;

		if ( SAME_COLOR (x, y, dx, dy) )
		{
			send_to_char( ch, "Non posso mangiare un pezzo del mio stesso colore.\r\n" );
			return MOVE_SAMECOLOR;
		}

		return MOVE_TAKEN;
	  }
	  break;

	  case PIECE_KING:
	  {
		int		sp;
		int		spc;
		int		sk;
		int		skc;
		bool	incheck = FALSE;;

		if ( dx > x+1 || dx < x-1 || dy > y+1 || dy < y-1 )
		{
			send_to_char( ch, "Posso muovere il re di un solo passo attorno a sè, non oltre.\r\n" );
			return MOVE_INVALID;
		}

		if ( SAME_COLOR(x, y, dx, dy) )
		{
			send_to_char( ch, "Non posso mangiare un pezzo del mio stesso colore.\r\n" );
			return MOVE_SAMECOLOR;
		}

		sk	= board->piece[x][y];
		skc = board->color[x][y];
		sp	= board->piece[dx][dy];
		spc	= board->color[dx][dy];
		board->piece[x][y] = PIECE_NONE;
		board->piece[x][y] = COLOR_NONE;
		board->piece[dx][dy] = sk;
		board->color[dx][dy] = skc;

		if ( king_in_check(board, sk, skc) > 0 )
			incheck = TRUE;

		board->piece[x][y]	 = sk;
		board->color[x][y]	 = skc;
		board->piece[dx][dy] = sp;
		board->color[dx][dy] = spc;

		if ( incheck )
		{
			send_to_char( ch, "Non posso muovere il re in quella casella, sarebbe sotto scacco.\r\n" );
			return MOVE_CHECK;
		}

		if ( board->piece[dx][dy] == PIECE_NONE )
			return MOVE_OK;

		return MOVE_TAKEN;
	  }
	  break;
	}

	send_log( NULL, LOG_BUG, "is_valid_move: shouldn't get here" );
	send_to_char( ch, "-> Mossa sbagliata, avverti i Coder <-" );
	return MOVE_INVALID;
}
Ejemplo n.º 10
0
/*
 * Controlla se il re sia in possibile scacco matto
 * (TT) Purtroppo questa parte è parziale, visto che si potrebbe coprire lo scacco con
 *	uno spostamento di un'altro pezzo, bisogna vedere in gioco come si comporta
 */
static bool king_in_possible_checkmate( CHESSBOARD_DATA *board, const int piece, const int color )
{
	int	x = 0;
	int	y = 0;
	int direction;

	if ( !board )
	{
		send_log( NULL, LOG_BUG, "king_in_possible_checkmate: board passata è NULL" );
		return FALSE;
	}

	if ( piece < 0 || piece >= PIECE_NONE )
	{
		send_log( NULL, LOG_BUG, "king_in_possible_checkmate: pezzo passato errato: %d", piece );
		return FALSE;
	}

	if ( color < 0 || color >= COLOR_NONE )
	{
		send_log( NULL, LOG_BUG, "king_in_possibile_checkmate: color passato è errato: %d", color );
		return FALSE;
	}

	if ( piece != PIECE_KING )
		return FALSE;

	/* Cercando il re nella scacchiera ritorna le coordinate del pezzo */
	if ( !find_piece(board, &x, &y, piece) )
		return FALSE;

	if ( x < 0 || y < 0 || x >= 8 || y >= 8 )
	{
		send_log( NULL, LOG_BUG, "king_in_possible_checkmate: coordinate del pezzo %s errate: x=%d y=%d",
			table_pieces[piece].name, x, y );
		return FALSE;
	}

	if ( king_in_check(board, board->piece[x][y], board->color[x][y]) == 0 )
		return FALSE;

	for ( direction = 0;  direction < 8;  direction++ )
	{
		int		dirx = 0;
		int		diry = 0;
		int		sk	= -1;
		int		skc = -1;
		bool	incheck = FALSE;

		switch ( direction )
		{
		  case 0:	dirx = x + 1;		diry = y + 1;
		  case 1:	dirx = x - 1;		diry = y + 1;
		  case 2:	dirx = x + 1;		diry = y - 1;
		  case 3:	dirx = x - 1;		diry = y - 1;
		  case 4:	dirx = x;			diry = y + 1;
		  case 5:	dirx = x;			diry = y - 1;
		  case 6:	dirx = x + 1;		diry = y;
		  case 7:	dirx = x - 1;		diry = y;
		}

		if ( dirx <  0 )	continue;
		if ( dirx >= 8 )	continue;
		if ( diry <  0 )	continue;
		if ( diry >= 8 )	continue;

		if ( board->piece[dirx][diry] == PIECE_NONE )
		{
			sk	= board->piece[dirx][diry] = board->piece[x][y];
			skc = board->color[dirx][diry] = board->color[x][y];
			board->piece[x][y] = PIECE_NONE;
			board->color[x][y] = COLOR_NONE;
			if ( king_in_check(board, sk, skc) == 0 )
				incheck = TRUE;

			board->piece[x][y] = sk;
			board->color[x][y] = skc;
			board->piece[dirx][diry] = PIECE_NONE;
			board->color[dirx][diry] = COLOR_NONE;

			if ( incheck )
				return FALSE;
		}
	}

	return TRUE;
}
Ejemplo n.º 11
0
/*
 * Comando per gestire il gioco degli scacchi
 */
void do_chess( CHAR_DATA *ch, char *argument )
{
	CHESSBOARD_DATA *board;
	char			 arg[MIL];

	if ( !ch )
	{
		send_log( NULL, LOG_BUG, "do_chess: ch è NULL" );
		return;
	}

	if ( IS_MOB(ch) )
	{
		send_to_char( ch, "I mob non possono giocare a scacchi.\r\n" );
		return;
	}

	board = get_chessboard( ch );

	if ( !VALID_STR(argument) || is_name(argument, "sintassi aiuto syntax help ?") )
	{
		char	*cmd;

		cmd = translate_command( ch, "chess" );
		ch_printf( ch, "&YSintassi gioco&w:  %s inizio|smetto|partecipo|forfeit\r\n", cmd );
		ch_printf( ch, "&YSintassi info&w:   %s pezzi\r\n", cmd );
		ch_printf( ch, "&YSintassi mosse&w:  %s muovo <sorgente> <destinazione> [comandi opzionali]\r\n", cmd );
		ch_printf( ch, "&YSintassi extra&w:  %s arrocco|promuovo\r\n", cmd );

		if ( !VALID_STR(argument) && board )
		{
			send_to_char( ch, "\r\n" );
			show_status( ch, board );
			send_to_char( ch, "\r\n" );
			show_board( ch, board );
		}

		return;
	}

	argument = one_argument( argument, arg );

	if ( is_name_prefix(arg, "inizio inizia comincio comincia cominciare start") )
	{
		CHESSBOARD_DATA *newboard;

		if ( board )
		{
			send_to_char( ch, "Sto già partecipando ad una partita di scacchi.\r\n" );
			return;
		}

		CREATE( newboard, CHESSBOARD_DATA, 1 );
		init_board( newboard );
		newboard->player1	= ch;
		newboard->turn		= ch;

		LINK( newboard, first_chessboard, last_chessboard, next, prev );
		top_chessboard++;

		send_to_char( ch, "Inizio una nuova partita di scacchi.\r\n" );
		return;
	}

	if ( is_name_prefix(arg, "partecipa partecipo join") )
	{
		CHESSBOARD_DATA *vboard = NULL;
		CHAR_DATA		*vch;
		char			 arg2[MIL];

		if ( board )
		{
			send_to_char( ch, "Sto già partecipando ad una partita di scacchi.\r\n" );
			return;
		}

		argument = one_argument( argument, arg2 );
		if ( !VALID_STR(arg2) )
		{
			send_to_char( ch, "Con chi devo partecipare ad una partita di scacchi?\r\n" );
			return;
		}

		vch = get_player_room( ch, arg2, TRUE );
		if ( !vch )
		{
			ch_printf( ch, "Non vedo nessun %s nella stanza.\r\n", arg2 );
			return;
		}

		vboard = get_chessboard( vch );
		if ( !vboard )
		{
			send_to_char( ch, "Non sta giocando a scacchi.\r\n" );
			return;
		}

		if ( vboard->player2 )
		{
			send_to_char( ch, "Questa scacchiera ha già due giocatori.\r\n" );
			return;
		}

		vboard->player2 = ch;
		vboard->turn	= vboard->player2;

		send_to_char( ch, "Mi unisco alla partita, è il mio turno.\r\n" );
		ch_printf( vboard->player1, "%s si unisce alla tua partita.\r\n", ch->name );
		return;
	}

	if ( is_name_prefix(arg, "pezzi pieces") )
	{
		int		x;	/* contatore dei colori */
		int		y;	/* contatore dei pezzi */

		for ( x = 0;  x < COLOR_NONE;  x++ )
		{
			if ( x == COLOR_BLACK )
				send_to_char( ch, "\r\n\r\nPezzi neri:\r\n" );
			else
				send_to_char( ch, "Pezzi bianchi:\r\n" );

			for ( y = PIECE_PAWN;  y < PIECE_NONE;  y++ )
				ch_printf( ch, "%-7s", table_pieces[y].name );

			send_to_char( ch, "\r\n" );
			for ( y = PIECE_PAWN;  y < PIECE_NONE;  y++ )
				send_to_char( ch, (x == COLOR_WHITE) ? table_pieces[y].wgraph1 : table_pieces[y].bgraph1 );

			send_to_char( ch, "\r\n" );
			for ( y = PIECE_PAWN;  y < PIECE_NONE;  y++ )
				send_to_char( ch, (x == COLOR_WHITE) ? table_pieces[y].wgraph2 : table_pieces[y].bgraph2 );
		}
		send_to_char( ch, "\r\n" );
		return;
	}

	if ( !board )
	{
		send_to_char( ch, "Non ho iniziato o non sto partecipando a nessuna partita di scacchi.\r\n" );
		return;
	}

	if ( is_name_prefix(arg, "smetto fermo stop") )
	{
		free_chessboard( board );
		return;
	}

	if ( is_name_prefix(arg, "forfeit") )
	{
		send_to_char( ch, "Dò forfeit così perdendo.\r\n" );
		free_chessboard( board );
		return;
	}

	if ( !board->player1 || !board->player2 )
	{
		send_to_char( ch, "C'è solo un giocatore.\r\n" );
		return;
	}

	if ( board->moves < 0 )
	{
		send_to_char( ch, "Il gioco non è ancora iniziato.\r\n" );
		return;
	}

	if ( is_name_prefix(arg, "promuovo promuovi promote") )
	{
		int		piece = board->piece[board->lastx][board->lasty];
		char	extra[MIL];

		if ( !((piece == PIECE_PAWN && board->player1 == ch)
		  ||   (piece == PIECE_PAWN && board->player2 == ch)) )
		{
			send_to_char( ch, "Non posso promuovere questo pezzo.\r\n" );
			return;
		}

		if ( (piece == PIECE_PAWN && board->lastx != 0)
		  || (piece == PIECE_PAWN && board->lastx != 7) )
		{
			send_to_char( ch, "Puoi promuovere solamente i pedoni che hanno raggiunto l'altro lato della scacchiera.\r\n" );
			return;
		}

		if ( !VALID_STR(argument) )
		{
			send_to_char( ch, "Vorrei promuovere il pedone in che cosa?\r\n" );
			return;
		}

		if		( is_name_prefix(argument, "regina queen"  ) )	piece = PIECE_QUEEN;
		else if ( is_name_prefix(argument, "alfiere bishop") )	piece = PIECE_BISHOP;
		else if ( is_name_prefix(argument, "cavallo knight") )	piece = PIECE_KNIGHT;
		else if ( is_name_prefix(argument, "torre rook"	   ) )	piece = PIECE_ROOK;
		else
		{
			ch_printf( ch, "Non posso promuoverlo a %s.\r\n", argument );
			return;
		}

		board->piece[board->lastx][board->lasty] = piece;
		sprintf( extra, "%s (%c%d)", table_pieces[piece].name, board->lastx+'a', board->lasty+1 );
		board_move_messages( ch, MOVE_PROMOTE, extra );
		return;
	}

	if ( board->turn != ch )
	{
		send_to_char( ch, "Non è il mio turno.\r\n" );
		return;
	}

	if ( is_name_prefix(arg, "arrocco") )
	{
		int 	myx;
		int 	rooky;
		int 	kdy;
		int		rdy;
		bool	fRookShort;

		if ( king_in_check(board, PIECE_KING, (board->player1 == ch) ? COLOR_BLACK : COLOR_WHITE) > 0 )
		{
			send_to_char( ch, "Non posso eseguire un arrocco mentre sono sotto scacco.\r\n" );
			return;
		}

		if ( (board->player1 == ch && HAS_BIT(board->flags1, CHESSFLAG_MOVEDKING))
		  || (board->player2 == ch && HAS_BIT(board->flags2, CHESSFLAG_MOVEDKING)) )
		{
			send_to_char( ch, "Non posso effettuare un arrocco quando ho già mosso il mio re.\r\n" );
			return;
		}
		myx = (board->player1 == ch) ? 7 : 0;

		if ( !VALID_STR(argument) )
		{
			ch_printf( ch, "Utilizzo: %s arrocco corto|lungo\r\n", translate_command(ch, "chess") );
			return;
		}

		if ( is_name_prefix(argument, "corto short") )
			fRookShort = TRUE;
		else if ( is_name_prefix(argument, "lungo long") )
			fRookShort = FALSE;
		else
		{
			send_command( ch, "chess arrocco", CO );
			return;
		}

		if ( (board->player1 == ch && HAS_BIT(board->flags1, fRookShort ? CHESSFLAG_MOVEDKROOK : CHESSFLAG_MOVEDQROOK))
		  || (board->player2 == ch && HAS_BIT(board->flags2, fRookShort ? CHESSFLAG_MOVEDKROOK : CHESSFLAG_MOVEDQROOK)) )
		{
			ch_printf( ch, "Non posso effettuare l'arrocco %s perchè ho già mosso la torre prima.\r\n",
				fRookShort ? "corto" : "lungo" );
			return;
		}
		rooky = fRookShort ? 7 : 0;

		if ( ( fRookShort && (board->piece[myx][6] != PIECE_NONE || board->piece[myx][5] != PIECE_NONE))
		  || (!fRookShort && (board->piece[myx][1] != PIECE_NONE || board->piece[myx][2] != PIECE_NONE || board->piece[myx][3] != PIECE_NONE)) )
		{
			send_to_char( ch, "L'arrocco è bloccato dalla presenza di pezzi tra il re e la torre.\r\n" );
			return;
		}

		/* castling succeeded */
		if ( fRookShort )
		{
			kdy = 6;
			rdy = 5;
		}
		else
		{
			kdy = 2;
			rdy = 3;
		}

/* (FF) (TT) (RR) (bb) ricordo che una qualsiasi delle caselle, in cui avveniva l'arrocco
 *	non dovevano essere sotto scacco, mi sa che qui non è così, o forse ricordo sbagliato */

		/* check for 'move across check' rule */
		board->piece[myx][rdy] = board->piece[myx][4];
		board->piece[myx][4] = PIECE_NONE;

		if ( king_in_check(board, board->piece[myx][rdy], board->color[myx][rdy]) > 0 )
		{
			send_to_char( ch, "Il mio re si troverebbe sotto scacco dopo l'arrocco.\r\n" );

			board->piece[myx][4] = board->piece[myx][rdy];
			board->piece[myx][rdy] = PIECE_NONE;
			return;
		}

		board->piece[myx][kdy] = board->piece[myx][rdy];
		board->piece[myx][rdy] = board->piece[myx][rooky];
		board->piece[myx][rooky] = PIECE_NONE;

		/* check for 'check' after castled */
		if ( king_in_check(board, board->piece[myx][kdy], board->color[myx][kdy]) > 0 )
		{
			send_to_char( ch, "Il mio re si troverebbe sotto scacco dopo l'arrocco.\r\n" );

			board->piece[myx][4] = board->piece[myx][kdy];
			board->piece[myx][kdy] = PIECE_NONE;
			board->piece[myx][rooky] = board->piece[myx][rdy];
			board->piece[myx][rdy] = PIECE_NONE;
			return;
		}

		/* Basta indicare che è stato mosso il re per evitare un altro arrocco */
		if ( board->player1 == ch )
			SET_BIT( board->flags1, CHESSFLAG_MOVEDKING );
		else
			SET_BIT( board->flags2, CHESSFLAG_MOVEDKING );

		board_move_stuff( board );
		board_move_messages( ch, MOVE_CASTLE, rooky == 7 ? "corto" : "lungo" );
	}

	if ( is_name_prefix(arg, "muovo move") )
	{
		char	coord1[MIL];
		char	coord2[MIL];
		char	extra[MIL];
		int		x, y, dx, dy;
		int		ret;

		if ( !VALID_STR(argument) )
		{
			ch_printf( ch, "Utilizzo: %s muovo <sorgente> <destinazione>\r\n", translate_command(ch, "chess") );
			return;
		}

		argument = one_argument( argument, coord1 );
		argument = one_argument( argument, coord2 );

		if ( !VALID_STR(coord1) || !VALID_STR(coord2) )
		{
			ch_printf( ch, "Utilizzo: %s muovo <sorgente> <destinazione>\r\n", translate_command(ch, "chess") );
			return;
		}

		get_coord( coord1, &x, &y );
		get_coord( coord2, &dx, &dy );

		if ( x < 0 || x >= 8 || dx < 0 || dx >= 8
		  || y < 0 || y >= 8 || dy < 0 || dy >= 8 )
		{
			send_to_char( ch, "Mossa non valida, utilizza a-h e 1-8 (esempio: a4 b4).\r\n" );
			return;
		}

		extra[0] = '\0';

		ret = is_valid_move( ch, board, x, y, dx, dy );
		if ( ret == MOVE_OK || ret == MOVE_TAKEN )
		{
			int	piece;
			int	color;
			int	destpiece;
			int	destcolor;

			piece	  = board->piece[x][y];
			color	  = board->color[x][y];
			destpiece = board->piece[dx][dy];
			destcolor = board->color[dx][dy];

			board->piece[dx][dy] = piece;
			board->color[dx][dy] = color;
			board->piece[x][y] = PIECE_NONE;
			board->color[x][y] = COLOR_NONE;

			if ( king_in_check(board, PIECE_KING, board->color[dx][dy]) > 0 )
			{
				board->piece[dx][dy] = destpiece;
				board->color[dx][dy] = destcolor;
				board->piece[x][y]	 = piece;
				board->color[x][y]	 = color;
				ret = MOVE_INCHECK;
			}
			else
			{
				if ( destpiece == PIECE_NONE )
					sprintf( extra, "%c%d (%s) alle coordinate %c%d", x+'a', y+1, table_pieces[piece].name, y+'a', dy+1 );
				else
					sprintf( extra, "%c%d (%s) alle coordinate %c%d (%s)", x+'a', y+1, table_pieces[piece].name, y+'a', dy+1, table_pieces[destpiece].name );

				board_move_stuff( board );
				board->lastx = dx;
				board->lasty = dy;

				/* Imposta le flag per evitare gli arrocchi */
				if ( piece == PIECE_ROOK )
				{
					if ( color == COLOR_WHITE )
					{
						if ( y == 0 && x == 0 )
							SET_BIT( board->flags1, CHESSFLAG_MOVEDKROOK );
						else if ( y == 0 && x == 7 )
							SET_BIT( board->flags1, CHESSFLAG_MOVEDQROOK );
					}
					else
					{
						if ( y == 7 && x == 0 )
							SET_BIT( board->flags2, CHESSFLAG_MOVEDKROOK );
						else if ( y == 7 && x == 7 )
							SET_BIT( board->flags2, CHESSFLAG_MOVEDQROOK );
					}
				}
				else if ( piece == PIECE_KING )
				{
					if ( color == COLOR_WHITE )
						SET_BIT( board->flags1, CHESSFLAG_MOVEDKING );
					else
						SET_BIT( board->flags2, CHESSFLAG_MOVEDKING );
				}
			}

			board_move_messages( ch, ret, extra );
		}

		/* Così qui gestisce i comandi opzionali, come il promote */
		if ( VALID_STR(argument) )
		{
			do_chess( ch, argument );
			return;
		}
		return;
	}

	send_command( ch, "chess aiuto", CO );
}