#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define INF 10000000 char king[10], rook1[10], rook2[10]; int T; int D[2][1 << 6][1 << 6][1 << 6]; inline int getRow(int mask) { return mask >> 3; } inline int getCol(int mask) { return mask & 7; } inline int encode(int row, int col) { return (row << 3) | col; } int encode(char piece[10]) { int row = piece[1] - '1'; int col = piece[0] - 'a'; return encode(row, col); } struct state { int t, k, r1, r2; state(int t, int k, int r1, int r2) : t(t), k(k), r1(r1), r2(r2) { } state(const state &s) : t(s.t), k(s.k), r1(s.r1), r2(s.r2) { } bool operator ==(const state &s) const { return t == s.t && k == s.k && r1 == s.r1 && r2 == s.r2; } bool operator <(const state &s) const { if(t != s.t) return t < s.t; if(k != s.k) return k < s.k; if(r1 != s.r1) return r1 < s.r1; return r2 < s.r2; } }; namespace std { namespace tr1 { template<> struct hash { std::size_t operator()(const state &key) const { return (key.t * 666013 + key.k + key.r1 * (1 << 6) + key.r2 * (1 << 12)); } }; } } tr1::unordered_set B, W; vector lastB, lastW; bool isCheckmate(int k, int r1, int r2) { int kRow = getRow(k); int kCol = getCol(k); int r1Row = getRow(r1); int r1Col = getCol(r1); int r2Row = getRow(r2); int r2Col = getCol(r2); // check if it's valid if(k == r1 || k == r2 || r1 == r2) return false; if(r1Row > r2Row) { swap(r1Row, r2Row); swap(r1Col, r2Col); } if(kRow == 0) { if(r1Row == 0 && r2Row == 1) { if(abs(kCol - r1Col) > 1 && abs(kCol - r2Col) > 1) return true; } } if(kRow == 7) { if(r1Row == 6 && r2Row == 7) { if(abs(kCol - r1Col) > 1 && abs(kCol - r2Col) > 1) return true; } } if(r1Col > r2Col) { swap(r1Row, r2Row); swap(r1Col, r2Col); } if(kCol == 0) { if(r1Col == 0 && r2Col == 1) { if(abs(kRow - r1Row) > 1 && abs(kRow - r2Row) > 1) return true; } } if(kCol == 7) { if(r1Col == 6 && r2Col == 7) { if(abs(kRow - r1Row) > 1 && abs(kRow - r2Row) > 1) return true; } } return false; } bool canCapture(int k, int r1, int r2) { int kRow = getRow(k); int kCol = getCol(k); int r1Row = getRow(r1); int r1Col = getCol(r1); int r2Row = getRow(r2); int r2Col = getCol(r2); // check if it's valid if(k == r1 || k == r2 || r1 == r2) return false; // the rooks defend each other if(r1Row == r2Row || r1Col == r2Col) return false; if(max(abs(kRow - r1Row), abs(kCol - r1Col)) <= 1) return true; if(max(abs(kRow - r2Row), abs(kCol - r2Col)) <= 1) return true; return false; } void generateMoves(state &s, vector &v) { int t = s.t; int k = s.k; int r1 = s.r1; int r2 = s.r2; int kRow = getRow(k); int kCol = getCol(k); int r1Row = getRow(r1); int r1Col = getCol(r1); int r2Row = getRow(r2); int r2Col = getCol(r2); if(t == 0) { // white to move // rook1 moves for(int row = 0; row < 8; row++) if(row != r1Row) { int nr1 = encode(row, r1Col); if(nr1 != r2 && nr1 != k) v.push_back(state(1 - t, k, nr1, r2)); } for(int col = 0; col < 8; col++) if(col != r1Col) { int nr1 = encode(r1Row, col); if(nr1 != r2 && nr1 != k) v.push_back(state(1 - t, k, nr1, r2)); } // rook2 moves for(int row = 0; row < 8; row++) if(row != r2Row) { int nr2 = encode(row, r2Col); if(nr2 != r1 && nr2 != k) v.push_back(state(1 - t, k, r1, nr2)); } for(int col = 0; col < 8; col++) if(col != r2Col) { int nr2 = encode(r2Row, col); if(nr2 != r1 && nr2 != k) v.push_back(state(1 - t, k, r1, nr2)); } } else { // black to move for(int row = kRow - 1; row <= kRow + 1; row++) for(int col = kCol - 1; col <= kCol + 1; col++) if((row != kRow || col != kCol) && row >= 0 && row < 8 && col >= 0 && col < 8) { int nk = encode(row, col); if(nk != r1 && nk != r2) { // can't capture (it's defended) // must not move into check if(row != r1Row && row != r2Row && col != r1Col && col != r2Col) v.push_back(state(1 - t, nk, r1, r2)); } } } } void generateUnmoves(state &s, vector &v) { int t = s.t; int k = s.k; int r1 = s.r1; int r2 = s.r2; int kRow = getRow(k); int kCol = getCol(k); int r1Row = getRow(r1); int r1Col = getCol(r1); int r2Row = getRow(r2); int r2Col = getCol(r2); if(t == 1) { // white to move // rook1 moves for(int row = 0; row < 8; row++) if(row != r1Row) { if((r1Col != r2Col) || (row < r2Row) == (r1Row < r2Row)) { // can't jump over int nr1 = encode(row, r1Col); if(nr1 != r2 && nr1 != k) { v.push_back(state(1 - t, k, nr1, r2)); } } } for(int col = 0; col < 8; col++) if(col != r1Col) { if((r1Row != r2Row) || (col < r2Col) == (r1Col < r2Col)) { // can't jump over int nr1 = encode(r1Row, col); if(nr1 != r2 && nr1 != k) v.push_back(state(1 - t, k, nr1, r2)); } } // rook2 moves for(int row = 0; row < 8; row++) if(row != r2Row) { if((r1Col != r2Col) || (row < r1Row) == (r2Row < r1Row)) { // can't jump over int nr2 = encode(row, r2Col); if(nr2 != r1 && nr2 != k) v.push_back(state(1 - t, k, r1, nr2)); } } for(int col = 0; col < 8; col++) if(col != r2Col) { if((r1Row != r2Row) || (col < r1Col) == (r2Col < r1Col)) { // can't jump over int nr2 = encode(r2Row, col); if(nr2 != r1 && nr2 != k) v.push_back(state(1 - t, k, r1, nr2)); } } } else { // black to move // must not come from check if(kRow != r1Row && kRow != r2Row && kCol != r1Col && kCol != r2Col) { for(int row = kRow - 1; row <= kRow + 1; row++) for(int col = kCol - 1; col <= kCol + 1; col++) if((row != kRow || col != kCol) && row >= 0 && row < 8 && col >= 0 && col < 8) { int nk = encode(row, col); if(nk != r1 && nk != r2) v.push_back(state(1 - t, nk, r1, r2)); } } } } bool isCertainlyLosing(state &s) { if(canCapture(s.k, s.r1, s.r2)) return false; vector moves; generateMoves(s, moves); for(vector :: iterator it = moves.begin(); it != moves.end(); it++) if(W.count(*it) == 0) return false; return true; } void generate() { for(int k = 0; k < (1 << 6); k++) for(int r1 = 0; r1 < (1 << 6); r1++) for(int r2 = 0; r2 < (1 << 6); r2++) { if(isCheckmate(k, r1, r2)) { lastB.push_back(state(1, k, r1, r2)); B.insert(state(1, k, r1, r2)); } } int numMoves = 0; while(lastB.size() > 0) { cerr << numMoves << ' ' << B.size() << ' ' << W.size() << ' ' << lastB.size() << ' ' << lastW.size() << '\n'; lastW.clear(); for(vector :: iterator it = lastB.begin(); it != lastB.end(); it++) { D[it->t][it->k][it->r1][it->r2] = numMoves; vector moves; generateUnmoves(*it, moves); // cerr << moves.size() << '\n'; for(vector :: iterator parent = moves.begin(); parent != moves.end(); parent++) { if(W.count(*parent) == 0) { W.insert(*parent); lastW.push_back(*parent); } } } numMoves++; lastB.clear(); // cerr << numMoves << ' ' << B.size() << ' ' << W.size() << ' ' << lastB.size() << ' ' << lastW.size() << '\n'; for(vector :: iterator it = lastW.begin(); it != lastW.end(); it++) { D[it->t][it->k][it->r1][it->r2] = numMoves; vector moves; generateUnmoves(*it, moves); for(vector :: iterator parent = moves.begin(); parent != moves.end(); parent++) { if(B.count(*parent) == 0) { if(isCertainlyLosing(*parent)) { B.insert(*parent); lastB.push_back(*parent); } } } } } } int main() { generate(); // freopen("date.in", "r", stdin); // freopen("date.out","w", stdout); scanf("%d\n", &T); while(T--) { scanf("%s %s %s\n", king, rook1, rook2); int k = encode(king); int r1 = encode(rook1); int r2 = encode(rook2); printf("%d\n", D[0][k][r1][r2]); } return 0; }