// 亚马逊棋（Amazons）蒙特卡洛AI程序 - 优化版
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <cmath>
#include <algorithm>
#include <random>
#include <chrono>
#include <queue>
#include <cstring>  // 添加memset

#define GRIDSIZE 8
#define OBSTACLE 2
#define judge_black 0
#define judge_white 1
#define grid_black 1
#define grid_white -1

using namespace std;

// 均衡型参数配置
const double CONTROL_FACTOR = 1.0;
const double SAFETY_FACTOR = 1.0;
const double SURROUND_FACTOR = 10.0;
const double CENTER_FACTOR = 1.0;

// 蒙特卡洛参数 - 减少模拟次数提高速度
const int SIMULATIONS_PER_MOVE = 15;  // 减少模拟次数
const int MAX_SIMULATION_STEPS = 5;   // 减少模拟步数
const int MCTS_ITERATIONS = 50;       // 减少迭代次数

// 预计算方向向量
const int dx[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dy[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };

int currBotColor;
int gridInfo[GRIDSIZE][GRIDSIZE] = { 0 };

// 随机数生成器
static mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

// 走法结构体 - 紧凑表示
struct Move {
    unsigned char x0, y0, x1, y1, x2, y2;
    
    Move(int x0=0, int y0=0, int x1=0, int y1=0, int x2=0, int y2=0) 
        : x0(x0), y0(y0), x1(x1), y1(y1), x2(x2), y2(y2) {}
    
    bool isValid() const { return x0 != 255; }
};

// 移动缓存结构
struct MoveCache {
    int pieceX, pieceY;
    int moveCount;
    int moves[56]; // 最大可能移动数：8个方向 * 7步 = 56
    
    MoveCache() : pieceX(-1), pieceY(-1), moveCount(0) {
        memset(moves, 0, sizeof(moves));
    }
};

// 预计算中心距离
const double centerDistance[GRIDSIZE][GRIDSIZE] = {
    {9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90},
    {8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96},
    {8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06},
    {7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28},
    {7.28, 5.39, 4.03, 2.12, 2.12, 4.03, 5.39, 7.28},
    {8.06, 6.10, 4.95, 4.03, 4.03, 4.95, 6.10, 8.06},
    {8.96, 7.07, 6.10, 5.39, 5.39, 6.10, 7.07, 8.96},
    {9.90, 8.96, 8.06, 7.28, 7.28, 8.06, 8.96, 9.90}
};

// 全局移动列表缓存
vector<Move> allPossibleMoves;
vector<MoveCache> moveCache[2]; // 0:黑方, 1:白方

inline bool inMap(int x, int y) {
    return (unsigned)x < GRIDSIZE && (unsigned)y < GRIDSIZE;
}

// 快速棋盘复制（使用memcpy）
inline void copyBoard(const int src[GRIDSIZE][GRIDSIZE], int dst[GRIDSIZE][GRIDSIZE]) {
    memcpy(dst, src, sizeof(int) * GRIDSIZE * GRIDSIZE);
}

bool ProcStep(int x0, int y0, int x1, int y1, int x2, int y2, int color, bool check_only) {
    if (!inMap(x0, y0) || !inMap(x1, y1) || !inMap(x2, y2))
        return false;
    if (gridInfo[x0][y0] != color || gridInfo[x1][y1] != 0)
        return false;
    if (gridInfo[x2][y2] != 0 && !(x2 == x0 && y2 == y0))
        return false;
    
    if (!check_only) {
        gridInfo[x0][y0] = 0;
        gridInfo[x1][y1] = color;
        gridInfo[x2][y2] = OBSTACLE;
    }
    return true;
}

// 计算棋子的所有移动位置（优化版）
void calculateMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int x, int y, 
                       int moves[], int &count) {
    count = 0;
    int color = grid[x][y];
    if (color == 0) return;
    
    for (int d = 0; d < 8; ++d) {
        for (int step = 1; step < GRIDSIZE; ++step) {
            int xx = x + dx[d] * step;
            int yy = y + dy[d] * step;
            
            if (!inMap(xx, yy) || grid[xx][yy] != 0)
                break;
            
            moves[count++] = (xx << 3) | yy; // 使用位运算压缩坐标
        }
    }
}

// 预先计算所有棋子的移动
void precalculateMoves(const int grid[GRIDSIZE][GRIDSIZE], int color) {
    int idx = (color == grid_black) ? 0 : 1;
    moveCache[idx].clear();
    
    for (int i = 0; i < GRIDSIZE; ++i) {
        for (int j = 0; j < GRIDSIZE; ++j) {
            if (grid[i][j] == color) {
                MoveCache mc;
                mc.pieceX = i;
                mc.pieceY = j;
                calculateMovesFast(grid, i, j, mc.moves, mc.moveCount);
                if (mc.moveCount > 0) {
                    moveCache[idx].push_back(mc);
                }
            }
        }
    }
}

// 获取所有可能的走法（使用缓存）
vector<Move> getAllPossibleMovesFast(const int grid[GRIDSIZE][GRIDSIZE], int color) {
    vector<Move> moves;
    int idx = (color == grid_black) ? 0 : 1;
    
    // 如果缓存未计算，先计算
    if (moveCache[idx].empty()) {
        precalculateMoves(grid, color);
    }
    
    // 临时棋盘用于计算箭的位置
    int tempGrid[GRIDSIZE][GRIDSIZE];
    
    for (const auto& piece : moveCache[idx]) {
        for (int m = 0; m < piece.moveCount; ++m) {
            int movePos = piece.moves[m];
            int moveX = movePos >> 3;
            int moveY = movePos & 7;
            
            // 创建临时棋盘
            copyBoard(grid, tempGrid);
            tempGrid[moveX][moveY] = color;
            tempGrid[piece.pieceX][piece.pieceY] = 0;
            
            // 计算箭的位置
            int arrowMoves[56];
            int arrowCount = 0;
            calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount);
            
            for (int a = 0; a < arrowCount; ++a) {
                int arrowPos = arrowMoves[a];
                int arrowX = arrowPos >> 3;
                int arrowY = arrowPos & 7;
                moves.push_back(Move(piece.pieceX, piece.pieceY, moveX, moveY, arrowX, arrowY));
            }
        }
    }
    
    return moves;
}

// 快速局面评估（简化版）
double evaluateBoardFast(const int grid[GRIDSIZE][GRIDSIZE], int originalColor) {
    double score = 0.0;
    
    // 快速评估：只计算移动能力和中心控制
    for (int i = 0; i < GRIDSIZE; ++i) {
        for (int j = 0; j < GRIDSIZE; ++j) {
            int piece = grid[i][j];
            if (piece != 0 && piece != OBSTACLE) {
                // 中心控制
                double centerValue = (10.0 - centerDistance[i][j]) * CENTER_FACTOR;
                
                // 移动能力（简化计算）
                int moves[56];
                int moveCount = 0;
                calculateMovesFast(grid, i, j, moves, moveCount);
                double mobility = moveCount * CONTROL_FACTOR;
                
                if (piece == originalColor) {
                    score += centerValue + mobility;
                } else {
                    score -= centerValue + mobility;
                }
            }
        }
    }
    
    // 归一化
    return tanh(score / 50.0);
}

// 优化的随机游戏模拟
double simulateRandomGameFast(Move move, const int originalGrid[GRIDSIZE][GRIDSIZE], int color) {
    // 使用栈上数组，避免动态分配
    int simGrid[GRIDSIZE][GRIDSIZE];
    copyBoard(originalGrid, simGrid);
    
    // 执行第一步
    simGrid[move.x1][move.y1] = color;
    simGrid[move.x0][move.y0] = 0;
    simGrid[move.x2][move.y2] = OBSTACLE;
    
    int currentColor = -color;
    int steps = 0;
    
    // 快速随机模拟
    while (steps < MAX_SIMULATION_STEPS) {
        // 获取当前玩家的移动
        int moves[56];
        int moveCount = 0;
        bool hasMove = false;
        
        // 找到一个可以移动的棋子
        for (int i = 0; i < GRIDSIZE && !hasMove; ++i) {
            for (int j = 0; j < GRIDSIZE && !hasMove; ++j) {
                if (simGrid[i][j] == currentColor) {
                    calculateMovesFast(simGrid, i, j, moves, moveCount);
                    if (moveCount > 0) {
                        // 随机选择一个移动
                        int moveIdx = rng() % moveCount;
                        int movePos = moves[moveIdx];
                        int moveX = movePos >> 3;
                        int moveY = movePos & 7;
                        
                        // 计算箭的位置
                        int arrowMoves[56];
                        int arrowCount = 0;
                        
                        // 临时棋盘计算箭
                        int tempGrid[GRIDSIZE][GRIDSIZE];
                        copyBoard(simGrid, tempGrid);
                        tempGrid[moveX][moveY] = currentColor;
                        tempGrid[i][j] = 0;
                        calculateMovesFast(tempGrid, moveX, moveY, arrowMoves, arrowCount);
                        
                        if (arrowCount > 0) {
                            int arrowIdx = rng() % arrowCount;
                            int arrowPos = arrowMoves[arrowIdx];
                            int arrowX = arrowPos >> 3;
                            int arrowY = arrowPos & 7;
                            
                            // 执行移动
                            simGrid[moveX][moveY] = currentColor;
                            simGrid[i][j] = 0;
                            simGrid[arrowX][arrowY] = OBSTACLE;
                            hasMove = true;
                        }
                    }
                }
            }
        }
        
        if (!hasMove) break;
        
        currentColor = -currentColor;
        steps++;
    }
    
    return evaluateBoardFast(simGrid, color);
}

// 主决策函数
Move findBestMoveWithMonteCarlo() {
    // 清空缓存
    moveCache[0].clear();
    moveCache[1].clear();
    
    // 获取所有可能走法
    vector<Move> moves = getAllPossibleMovesFast(gridInfo, currBotColor);
    
    if (moves.empty()) {
        return Move(255, 255, 255, 255, 255, 255);
    }
    
    // 如果走法很少，直接返回第一个
    if (moves.size() == 1) {
        return moves[0];
    }
    
    Move bestMove = moves[0];
    double bestScore = -1e9;
    
    // 限制检查的走法数量
    int checkCount = min((int)moves.size(), 30);
    
    // 均匀采样，而不是检查所有走法
    vector<int> indices(moves.size());
    for (int i = 0; i < moves.size(); ++i) indices[i] = i;
    shuffle(indices.begin(), indices.end(), rng);
    
    for (int i = 0; i < checkCount; ++i) {
        int idx = indices[i];
        double totalScore = 0.0;
        
        // 减少模拟次数
        int sims = (i < 10) ? SIMULATIONS_PER_MOVE : (SIMULATIONS_PER_MOVE / 2);
        
        for (int sim = 0; sim < sims; ++sim) {
            totalScore += simulateRandomGameFast(moves[idx], gridInfo, currBotColor);
        }
        
        double avgScore = totalScore / sims;
        
        if (avgScore > bestScore) {
            bestScore = avgScore;
            bestMove = moves[idx];
        }
    }
    
    return bestMove;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    // 快速初始化棋盘
    memset(gridInfo, 0, sizeof(gridInfo));
    gridInfo[0][2] = gridInfo[2][0] = gridInfo[5][0] = gridInfo[7][2] = grid_black;
    gridInfo[0][5] = gridInfo[2][7] = gridInfo[5][7] = gridInfo[7][5] = grid_white;
    
    int turnID;
    cin >> turnID;
    
    currBotColor = grid_white;
    for (int i = 0; i < turnID; i++) {
        int x0, y0, x1, y1, x2, y2;
        cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2;
        
        if (x0 == -1) {
            currBotColor = grid_black;
        } else if (x0 >= 0) {
            ProcStep(x0, y0, x1, y1, x2, y2, -currBotColor, false);
        }
        
        if (i < turnID - 1) {
            cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2;
            if (x0 >= 0) {
                ProcStep(x0, y0, x1, y1, x2, y2, currBotColor, false);
            }
        }
    }
    
    // 决策
    Move bestMove = findBestMoveWithMonteCarlo();
    
    // 如果无效，使用简单策略
    if (!bestMove.isValid()) {
        // 简单策略：找到第一个合法走法
        vector<Move> moves = getAllPossibleMovesFast(gridInfo, currBotColor);
        if (!moves.empty()) {
            bestMove = moves[0];
        }
    }
    
    cout << (int)bestMove.x0 << ' ' << (int)bestMove.y0 << ' ' 
         << (int)bestMove.x1 << ' ' << (int)bestMove.y1 << ' ' 
         << (int)bestMove.x2 << ' ' << (int)bestMove.y2 << endl;
    
    return 0;
}