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; }
/* * 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 ); }
/* 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; }
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 ); }
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; }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
/* * 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 ); }