Sicily 1301. Chess

来源:互联网 发布:家庭电子相册制作软件 编辑:程序博客网 时间:2024/06/12 00:31

1301. Chess

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Chess is a game for two players, one with the "White" pieces and one with the "Black" pieces. At the beginning of the game, the pieces are set up as pictured below. (See diagrams below to identify pieces.) These hints will help you to remember the proper board setup:

1. Opposing Kings and Queens go directly opposite each other.

2. The square in the lower right hand corner is a light one.

3. The White Queen goes on a light square, the Black Queen on a dark square.

White always moves first, and then the players take turns moving. Only one piece may be moved at each turn (except for "castling," a special move that is explained later). The Knight is the only piece that can jump over other pieces. All other pieces move only along unblocked lines. You may not move a piece to a square already occupied by one of your own pieces. But you can capture an enemy piece that stands on a square where one of your pieces can move. Simply remove the enemy piece from the board and put your own piece in its place.

 The Pieces and How They Move

 The Queen

The Queen is the most powerful piece. She can move any number of squares in any direction: horizontal, vertical, or diagonal - if her path is not blocked. She can reach any of the squares with dots in this diagram.

The Rook

 

 

The Rook is the next most powerful piece. The Rook can move any number of squares vertically or horizontally if its path is not blocked.

The Bishop

 

 

The Bishop can move any number of squares diagonally if its path is not blocked. Note that this Bishop starts on a light square and can reach only other light squares. At the beginning of the game, you have one "dark-square" Bishop and one "light-square" Bishop.

The Knight

 

 

The Knight's move is special. It hops directly from its old square to its new square. The Knight can jump over other pieces between its old and new squares. Think of the Knight's move as an "L." It moves two squares horizontally or vertically and then makes a right-angle turn for one more square. The Knight always lands on a square opposite in color from its old square.

 

 

The King

 

 

The King is the most important piece. When he is trapped, his whole army loses. The King can move one square in any direction, for example, to any of the squares with dots in this diagram. (An exception is castling, which is explained later.) The King may never move into check, that is, onto a square attacked by an opponent's piece.

 The Pawn

 

 

The pawn moves straight ahead (never backward), but it captures diagonally. It moves one square at a time, but on its first move it has the option of moving forward one or two squares. In the diagram, the squares with dots indicate possible destinations for the pawns. The White pawn is on its original square, so it may move ahead either one or two squares. The Black pawn has already moved, so it may move ahead only one square at a time. The squares on which these pawns may capture are indicated by an X.

 

If a pawn advances all the way to the opposite end of the board, it is immediately "promoted" to another piece, usually a Queen. It may not remain a pawn or become a King. Therefore, it is possible for each player to have more than one Queen or more than two Rooks, Bishops, or Knights on the board at the same time. But I DO NOT want you to consider such situation in this problem.

 Special Moves

 Castling

 

 

Each player may "castle" only once during a game and when conditions are met. Castling is a special move that lets a player move two pieces at once - the King and one Rook. In castling, the player moves his King two squares to its left or right toward one of his Rooks. At the same time, the Rook involved goes to the square beside the King and toward the center of the board (see illustrations at left). In order to castle, neither the King nor the Rook involved may have moved before. Also, the King may not castle out of check, into check, or through check. Further, there may not be pieces of either color between the King and the Rook involved in castling.

 Castling is often a very important move because it allows you to place your King in a safe location and also allows the Rook to become more active.

 When the move is legal, each player has the choice of castling Kingside or Queenside or not at all, no matter what the other player chooses to do.

 En Passant

 

 

This French phrase is used for a special pawn capture. It means "in passing", and it occurs when one player moves a pawn two squares forward to try to avoid capture by the opponent's pawn. The capture is made exactly as if the player had moved the pawn only one square forward.

In the diagram, the Black pawn moves up two squares to the square with the dot. On its turn the White pawn may capture the Black one on the square marked with the X. If the White player does not exercise this option immediately - before playing some other move - the Black pawn is safe from "en passant" capture for the rest of the game. But new opportunities may arise for each pawn in similar circumstances.

 

 

For making the question simple, we assume that there are NO “En Passant” happened in the game.

 About Check and Checkmate

 The main goal of chess is to checkmate your opponent's King. The King is not actually captured and removed from the board like other pieces. But if the King is attacked ("checked") and threatened with capture, it must get out of check immediately. If there is no way to get out of check, the position is a "checkmate," and the side that is checkmated loses.

 You may not move into check. For example, moving into a direct line with your opponent's Rook, when if there are no other pieces between the Rook and your King, is not a legal move. Otherwise, the Rook could "capture" the King, which is not allowed.

 If you are in check, there are three ways of getting out:

1. Capturing the attacking piece;

2. Placing one of your own pieces between the attacker and your King (unless the attacker is a Knight);

3. Moving the King away from the attack.

 If a checked player can do none of these, he is checkmated and loses the game.

If a King is not in check, but that player can make no legal move, the position is called a stalemate and the game is scored as a draw, or tie.

 

How to Read and Write Chess

 There are many different ways to write chess moves. The most popular method is called algebraic notation (the method described below is not complete algebraic notation, I just made it simple). The main idea is that every square has a name like this:

 It looks very complicated but it's not! Each square on a chessboard has a first name (a letter) and a last name (a number). The letter identifies a file (column) and the number identifies a rank (row). Now, the important part is to know how to identify the pieces you are moving.

 You just need to use a single capital letter:

 K = King  Q = Queen  R = Rook  B = Bishop  N = Knight

 Note that "P" is not used. Chess players have agreed that a move without a letter — such as e4 — is understood to be a pawn move. You are almost ready to start using chess notation. Just pay attention to the following symbols:

 O-O = King-side castle

 O-O-O = Queen-side castle

 It’s a great idea to note your games. You can analyze and learn from your mistakes. We all make a lot of mistakes when we are learning a new thing. Don’t worry! Mistakes will help you improve your chess skills. Let’s put in practice what you are learning. We will use the famous "Scholar Mate," also called the four–move checkmate.

 

 

So, I can write chess moves like this.  

7

 e4 e5 Bc4 h6 Qh5 a5 Qf7  

 From this, you can know that the player with the “White” pieces won the game. Your job here is to judge the result from the given chess moves.  

Input

The input file will consist of a series games. Each game will start with a positive integer number n in a single line, which indicates the number of moves you will get in the game description. Then you can get a move list with n moves in the following n lines, a move in a line without any redundant spaces.

The input is terminated by a line with a single zero.

Output

For each game, you are supposed to give a judgment in a single line. The judgment should be one of the following statements.

No.

 

 

Statement

 

 

Remark

 

 

1

White Win

The play with the “White” pieces wins the game at the end of game

2

Black Win

The play with the “Black” pieces wins the game at the end of game

3

Stalemate

You can find the details about stalemate in the problem description

4

Draw

No one won the game, and no stalemate happened.

5

Dead Moves

After one play won the game or stalemate happened, there still are moves in the list

6

Puzzle Move

From the move you get, you can’t decide which chess should be moved

7

Illegal Move

Some move is illegal

If the game ended normally, you will get a statement between No.1 and No.4. If the game didn’t end normally, and there are not puzzle moves and illegal moves before where it should end, you will get a statement of No.5. Otherwise, output statement of No.6 or No.7 base on which you find first.

Sample Input

7e4e5Bc4h6Qh5a5Qf70

Sample Output

White Win

Problem Source

ZSUACM Team Member

// Problem#: 1301// Submission#: 3453650// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/// All Copyright reserved by Informatic Lab of Sun Yat-sen University#include <stdio.h>#include <string.h>#include <stdlib.h>enum TResult {    WHITEWIN = 1,    BLACKWIN,    STALEMATE,    DRAW,    DEAD,    PUZZLE,    ILLEGAL};const char RESULT[8][20] = {    "",    "White Win",    "Black Win",    "Stalemate",    "Draw",    "Dead Moves",    "Puzzle Move",    "Illegal Move"};enum TPieceType {    SPACE = 0,    PAWN,    KING,    QUEEN,    ROOK,    BISHOP,    KNIGHT};enum TSide {    NONE = 0,    WHITE,    BLACK};typedef struct {    TSide side;    TPieceType pt;}TPiece;typedef TPiece TBoard[8][8];int n;TResult result;bool wc, bc, w0rm, w7rm, b0rm, b7rm, wkm, bkm;TPieceType ChessType(char * mv) {    switch(mv[0]) {    case 'K': return KING;    case 'Q': return QUEEN;    case 'R': return ROOK;    case 'B': return BISHOP;    case 'N': return KNIGHT;    }    return PAWN;}void clear(TBoard b, int x, int y) {    b[x][y].side = NONE;    b[x][y].pt = SPACE;}void init(TBoard b) {    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            clear(b, i, j);        }    }    for (int i = 0; i < 8; i++) {        b[0][i].side = b[1][i].side = WHITE;        b[1][i].pt = PAWN;        b[7][i].side = b[6][i].side = BLACK;        b[6][i].pt = PAWN;    }    b[0][0].pt = b[0][7].pt = b[7][7].pt = b[7][0].pt = ROOK;    b[0][1].pt = b[0][6].pt = b[7][6].pt = b[7][1].pt = KNIGHT;    b[0][2].pt = b[0][5].pt = b[7][2].pt = b[7][5].pt = BISHOP;    b[0][3].pt = b[7][3].pt = QUEEN;    b[0][4].pt = b[7][4].pt = KING;}void skipInput(int k) {    char temp[20];    for (int i = k; i < n; i++)         scanf("%s", temp);}bool outOfBoard(int x, int y) {    if (x < 0 || y < 0) return true;    if (x >= 8 || y >= 8) return true;    return false;}bool canMoveP(TBoard b, int x, int y, int x2, int y2, int flag) {    if (flag == 1) {        if (y != y2 || b[x2][y2].side != NONE) return false;        if (b[x][y].side == WHITE) {            if (x == 1) {                return (x2 == 2 || (x2 == 3 && b[2][y].side == NONE));            } else {                return x2 == x + 1;            }        } else {            if (x == 6) return (x2 == 5 || (x2 == 4 && b[5][y].side == NONE));            else return x2 == x - 1;        }    } else {        if (b[x][y].side == WHITE) {            return (x2 == x + 1 && abs(y2 - y) == 1);        } else {            return (x2 == x - 1 && abs(y2 - y) == 1);        }    }    return false;}bool canMoveK(TBoard b, int x, int y, int x2, int y2) {    return (abs(x - x2) <= 1 && abs(y - y2) <= 1);}bool canMoveR(TBoard b, int x, int y, int x2, int y2) {    int dx, dy, xx, yy;    if (x != x2 && y != y2) return false;    if (x2 < x) dx = -1;    else dx = 1;    if (y2 < y) dy = -1;    else dy = 1;    if (x == x2) {        for (int i = 1; i < abs(y - y2); i++) {            yy = y + i * dy;            if (b[x][yy].side != NONE) return false;        }        return true;    }    for (int i = 1; i < abs(x - x2); i++) {        xx = x + i * dx;        if (b[xx][y].side != NONE) return false;    }    return true;}bool canMoveB(TBoard b, int x, int y, int x2, int y2) {    int dx, dy, xx, yy;    if (abs(x - x2) != abs(y - y2)) return false;    if (x2 < x) dx = -1;    else dx = 1;    if (y2 < y) dy = -1;    else dy = 1;    for (int i = 1; i < abs(x - x2); i++) {        xx = x + i * dx;        yy = y + i * dy;        if (b[xx][yy].side != NONE) return false;    }    return true;}bool canMoveQ(TBoard b, int x, int y, int x2, int y2) {    return canMoveR(b, x, y, x2, y2) || canMoveB(b, x, y, x2, y2);}bool canMoveN(int x, int y, int x2, int y2) {    int xx = abs(x - x2), yy = abs(y - y2);    return (xx + yy == 3 && (xx == 1 || yy == 1));}bool canMove(TBoard b, int x, int y, int x2, int y2, int flag) {    if (outOfBoard(x, y) || outOfBoard(x2, y2)) return false;    if (b[x][y].side == NONE) return false;    switch (b[x][y].pt) {    case PAWN: return canMoveP(b, x, y, x2, y2, flag);    case KING: return canMoveK(b, x, y, x2, y2);    case QUEEN: return canMoveQ(b, x, y, x2, y2);    case ROOK: return canMoveR(b, x, y, x2, y2);    case BISHOP: return canMoveB(b, x, y, x2, y2);    case KNIGHT: return canMoveN(x, y, x2, y2);    }    return false;}void chessMove(TBoard b, int x, int y, int x2, int y2) {    b[x2][y2].side = b[x][y].side;    b[x2][y2].pt = b[x][y].pt;    clear(b, x, y);}void getP(char * s, int & x2, int & y2) {    int k = 0;    if (s[0] < 'a') k = 1;    x2 = s[k + 1] - '1';    y2 = s[k] - 'a';}void getSourceP(TBoard b, int x2, int y2, int & x, int & y, TPieceType ct, TSide side) {    int flag = 1;    if (b[x2][y2].side != NONE) flag = 2;    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            if (b[i][j].side == side && b[i][j].pt == ct) {                if (canMove(b, i, j, x2, y2, flag)) {                    if (x == -1) {                        x = i;                        y = j;                    } else {                        x = -2;                        return;                    }                }            }        }    }}void markRM(TSide s, int x, int y) {    if (s == WHITE) {        if (x == 0) {            if (y == 0) w0rm = true;            if (y == 7) w7rm = true;        }        return;    }    if (x == 7) {        if (y == 0) b0rm = true;        if (y == 7) b7rm = true;    }}void move(TBoard b, char * s, TSide side) {    int x, y, x2, y2;    getP(s, x2, y2);    if (b[x2][y2].side == side) {        result = ILLEGAL;        return;    }    x = -1;    getSourceP(b, x2, y2, x, y, ChessType(s), side);    if (x == -1) {        result = ILLEGAL;        return;    }    if (x == -2) {        result = PUZZLE;        return;    }    if (b[x][y].pt == ROOK) markRM(side, x, y);    if (b[x][y].pt == KING) {        if (side == WHITE) wkm = true;        else bkm = true;    }    chessMove(b, x, y, x2, y2);}TSide opp(TSide side) {    if (side == BLACK) return WHITE;    return BLACK;}bool beAttack(TBoard b, int x, int y, TSide byWho) {    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            if (b[i][j].side == byWho && canMove(b, i, j, x, y, 2)) return true;        }    }    return false;}bool canCastle(TBoard b, TSide side, int flag) {    int row;    if (side == WHITE) {        if (wkm) return false;        if (flag == 3 && w7rm) return false;        if (flag == 5 && w0rm) return false;    } else {        if (bkm) return false;        if (flag == 3 && b7rm) return false;        if (flag == 5 && b0rm) return false;    }    if (side == WHITE) row = 0;    else row = 7;    if (flag == 5) {        for (int i = 1; i < 4; i++) {            if (b[row][i].side != NONE) return false;        }        for (int i = 0; i < 5; i++) {            if (beAttack(b, row, i, opp(side))) return false;        }    } else {        for (int i = 5; i < 7; i++) {            if (b[row][i].side != NONE) return false;        }        for (int i = 4; i < 8; i++) {            if (beAttack(b, row, i, opp(side))) return false;        }    }    return true;}void getKP(TBoard b, TSide side, int & x, int & y) {    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            if (b[i][j].pt == KING && b[i][j].side == side) {                x = i;                y = j;                return;            }        }    }}bool beCheck(TBoard b, TSide side) {    int x, y;    TSide op;    getKP(b, side, x, y);    op = opp(side);    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            if (b[i][j].side == op && canMove(b, i, j, x, y, 2)) return true;        }    }    return false;}void copyB(TBoard b2, TBoard b) {    for (int i = 0; i < 8; i++) {        for (int j = 0; j < 8; j++) {            b2[i][j].pt = b[i][j].pt;            b2[i][j].side = b[i][j].side;        }    }}bool noMove(TBoard b, TSide side) {    int x, y, x2, y2;    TBoard b2;    for (x = 0; x < 8; x++) {        for (y = 0; y < 8; y++) {            if (b[x][y].side == side) {                for (x2 = 0; x2 < 8; x2++) {                    for (y2 = 0; y2 < 8; y2++) {                        if ((x2 != x || y2 != y) && b[x][y].side != b[x2][y2].side && canMove(b, x, y, x2, y2, 1)) {                            if (b[x][y].pt == KING) {                                copyB(b2, b);                                chessMove(b2, x, y, x2, y2);                                if (!beCheck(b2, side)) {                                    return false;                                }                            } else {                                return false;                            }                        }                    }                }            }        }    }    return true;}void castle(TBoard b, TSide side, int flag) {    int row;    if (side == WHITE) {        if (wc) {            result = ILLEGAL;            return;        } else {            wc = true;        }    } else {        if (bc) {            result = ILLEGAL;            return;        } else {            bc = true;        }    }    if (canCastle(b, side, flag)) {        if (side == WHITE) {            row = 0;        } else {            row = 7;        }        if (flag == 3) {            chessMove(b, row, 4, row, 6);            chessMove(b, row, 7, row, 5);        } else {            chessMove(b, row, 4, row, 2);            chessMove(b, row, 0, row, 3);        }    } else {        result = ILLEGAL;    }}bool checkEnd(TBoard b, TSide side) {    int x, y, x2, y2;    TBoard b2;    if (!beCheck(b, side)) return false;    for (x = 0; x < 8; x++) {        for (y = 0; y < 8; y++) {            if (b[x][y].side == side) {                for (x2 = 0; x2 < 8; x2++) {                    for (y2 = 0; y2 < 8; y2++) {                        if ((x != x2 || y != y2) && b[x2][y2].side != side) {                            if (canMove(b, x, y, x2, y2, 1)) {                                copyB(b2, b);                                chessMove(b2, x, y, x2, y2);                                if (!beCheck(b2, side)) return false;                            }                            if (b[x][y].pt == PAWN && canMove(b, x, y, x2, y2, 2)) {                                copyB(b2, b);                                chessMove(b2, x, y, x2, y2);                                if (!beCheck(b2, side)) return false;                            }                        }                    }                }            }        }    }    return true;}void run(TBoard b) {    char s[20];    TSide side;    side = WHITE;    for (int i = 0; i < n; i++) {        if (result == WHITEWIN || result == BLACKWIN || result == STALEMATE) {            result = DEAD;            skipInput(i);            return;        }        scanf("%s", s);        if (s[0] != 'O') move(b, s, side);        else castle(b, side, strlen(s));        if (beCheck(b, side)) result = ILLEGAL;        if (result == PUZZLE || result == ILLEGAL) {            skipInput(i + 1);            return;        }        if (checkEnd(b, opp(side))) {            if (side == WHITE) {                result = WHITEWIN;            } else {                result = BLACKWIN;            }        }        side = opp(side);    }    if (result == DRAW && noMove(b, side)) result = STALEMATE;}int main() {    //std::ios::sync_with_stdio(false);    TBoard b;    while (scanf("%d", &n), n > 0) {        init(b);        result = DRAW;        wc = bc = w0rm = w7rm = b0rm = b7rm = wkm = bkm = false;        run(b);        printf("%s\n", RESULT[result]);    }    return 0;}                                 


0 0
原创粉丝点击