#include "strategic_player.h" #include "common.h" extern "C" IPlayer* PlayerFactory() { return new StrategicPlayer(); } // Helper functions inline int normalize(int x) { return (x + 1) >> 1; } inline char getPoint(Board &board, const int row, const int col) { return board(row, col); } inline bool isLineValid(Board &board, const int row, const int col) { return (row > -1 && row < board.GetRows() && col > -1 && col < board.GetCols()) && ((row & 1) != (col & 1)) && (getPoint(board, row, col) == ' '); } inline void set(Board &board, int r, int c, char ch) { board(r, c) = ch; } // string StrategicPlayer::PlayerInfo() { return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)"; } void StrategicPlayer::Init(int board_rows, int board_cols, char box_type, char line_type) { this->name = box_type; this->box_name = line_type; this->board.AllocateBoard(board_rows, board_cols); } StrategicPlayer::~StrategicPlayer() { board.FreeBoard(); } void StrategicPlayer::Close() { board.FreeBoard(); } /// TODO: check if we needs checks :) void StrategicPlayer::EventAddLine(char bar, const Loc &loc) { set(board, loc.row, loc.col, bar); } void StrategicPlayer::EventAddBox(char box, const Loc &loc) { set(board, loc.row, loc.col, box); } inline void selectLine(Board &board, int &row, int &col, int rows, int cols, char name) { int max_row = 2 * rows - 2; int max_col = 2 * cols - 2; // Step 1: Try to complete a box #pragma omp parallel for collapse(2) for (int r = 1; r < max_row; r += 2) { // Iterate over box centers (odd rows) for (int c = 1; c < max_col; c += 2) { // Iterate over box centers (odd cols) // Check adjacent lines for an opportunity to complete a box if (isLineValid(board, r - 1, c) && // Top line getPoint(board, r + 1, c) != ' ' && // Bottom line getPoint(board, r, c - 1) != ' ' && // Left line getPoint(board, r, c + 1) != ' ') { // Right line row = r - 1; col = c; return; } if (isLineValid(board, r + 1, c) && // Bottom line getPoint(board, r - 1, c) != ' ' && // Top line getPoint(board, r, c - 1) != ' ' && // Left line getPoint(board, r, c + 1) != ' ') { // Right line row = r + 1; col = c; return; } if (isLineValid(board, r, c - 1) && // Left line getPoint(board, r - 1, c) != ' ' && // Top line getPoint(board, r + 1, c) != ' ' && // Bottom line getPoint(board, r, c + 1) != ' ') { // Right line row = r; col = c - 1; return; } if (isLineValid(board, r, c + 1) && // Right line getPoint(board, r - 1, c) != ' ' && // Top line getPoint(board, r + 1, c) != ' ' && // Bottom line getPoint(board, r, c - 1) != ' ') { // Left line row = r; col = c + 1; return; } } } // Step 2: Avoid moves that leave a box with one line remaining #pragma omp parallel for collapse(2) for (int r = 0; r < 2 * rows - 1; ++r) { // Iterate over all valid rows for (int c = 0; c < 2 * cols - 1; ++c) { // Iterate over all valid cols if (isLineValid(board, r, c)) { // Simulate placing the line set(board, r, c, name); // Check if this move leaves a box with only one line remaining bool createsOpportunity = false; for (int nr = 1; nr < max_row; nr += 2) { // Iterate over box centers for (int nc = 1; nc < max_col; nc += 2) { if (getPoint(board, nr, nc) == ' ') { int adjacentLines = 0; if (nr > 0 && getPoint(board, nr - 1, nc) != ' ') adjacentLines++; // Top line if (nr < max_row && getPoint(board, nr + 1, nc) != ' ') adjacentLines++; // Bottom line if (nc > 0 && getPoint(board, nr, nc - 1) != ' ') adjacentLines++; // Left line if (nc < max_col && getPoint(board, nr, nc + 1) != ' ') adjacentLines++; // Right line if (adjacentLines == 3) { // Opponent can complete this box createsOpportunity = true; break; } } } if (createsOpportunity) break; } set(board, r, c, ' '); // Undo the simulated move if (!createsOpportunity) { row = r; col = c; return; } } } } // Step 3: Fallback to the first valid move #pragma omp parallel for collapse(2) for (int r = 0; r < 2 * rows - 1; ++r) { for (int c = 0; c < 2 * cols - 1; ++c) { if (isLineValid(board, r, c)) { row = r; col = c; return; } } } } Loc StrategicPlayer::SelectLineLocation() { int rows = normalize(board.GetRows()); int cols = normalize(board.GetCols()); int row, col; selectLine(board, row, col, rows, cols, name); return Loc(row, col); }