From a6a1fca8cd7b38fdc2dca27508b38e6c93ee7c94 Mon Sep 17 00:00:00 2001 From: Sandipsinh Rathod Date: Fri, 6 Dec 2024 21:24:11 -0500 Subject: [PATCH] add ss.* --- README.txt | 61 ++++++++++++ bar.so | Bin 28392 -> 0 bytes foo.so | Bin 60288 -> 0 bytes harshit/custom_player.cxx | 122 ----------------------- harshit/custom_player.h | 54 ---------- readme.txt | 10 -- strategic_player1.cxx => ss.cxx | 15 ++- strategic_player1.h => ss.h | 0 strategic_player.cxx | 171 -------------------------------- strategic_player.h | 38 ------- 10 files changed, 75 insertions(+), 396 deletions(-) create mode 100644 README.txt delete mode 100644 bar.so delete mode 100644 foo.so delete mode 100644 harshit/custom_player.cxx delete mode 100644 harshit/custom_player.h delete mode 100644 readme.txt rename strategic_player1.cxx => ss.cxx (94%) rename strategic_player1.h => ss.h (100%) delete mode 100644 strategic_player.cxx delete mode 100644 strategic_player.h diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..6a3bda8 --- /dev/null +++ b/README.txt @@ -0,0 +1,61 @@ +Team member 1: +Name: Sandipsinh Rathod +Email: sdr5549@psu.edu +Class: CMPSC 330 + +Team member 2: +Name: Sapan Shah +Email: scs6041@psu.edu +Class: CMPSC 330 +Homework 5 +Due Date: December 6, 2024 + +Command used to create object file for strategic player +g++ -O3 -shared -fPIC -ansi -pedantic -std=c++14 board.cxx ss.cxx -o SandipsinhRathodsdr5549_SapanShahscs6041.so + +Restructuring HW2 and HW4 in HW5 +1. Class Abstraction and Polymorphism + + HW2: The game logic was directly implemented without clear abstractions for players, relying on procedural logic. + HW4: Introduced polymorphism via Player, RandomPlayer, and StrategicPlayer classes. Players had distinct behavior, and polymorphism allowed dynamic handling of different player types. + HW5: Built on this by creating the StrategicPlayer1 class derived from IPlayer, implementing a robust and modular strategy for player decisions: + Interface Implementation: StrategicPlayer1 implements IPlayer, ensuring that all player-related behaviors are well-defined and standardized across implementations. + Enhanced Strategies: Added sophisticated methods like FindBoxCompletingMove and ForceOpponentMistake, making the strategy logic adaptable and focused on optimizing game outcomes. + +2. Dynamic Memory Management + + HW2: Basic memory management using raw pointers with manual deallocation. + HW4: Introduced the RAII (Resource Acquisition Is Initialization) pattern for managing board memory allocation and deallocation efficiently. + HW5: Continued RAII principles with a more structured approach to object lifecycles, ensuring robust cleanup: + Explicit initialization and cleanup methods (Init, Close) for the StrategicPlayer1 class. + Use of dynamic memory in a controlled and predictable way, minimizing risks of memory leaks. + +3. Board Representation + + HW2: The board was represented as a dynamically allocated 2D array, with logic scattered across functions. + HW4: Encapsulated board management into the Board class, which included methods for placing lines, checking box completion, and printing the board. + HW5: Enhanced the Board class functionality: + Added methods like ListEmptyLines to provide the player class with detailed insights into game state. + Improved the interface between the board and player, enabling complex strategic evaluations such as chain creation and cost evaluation. + +4. Player Strategies + + HW2: All moves were processed in a straightforward, procedural manner without differentiation between players. + HW4: Differentiated players using classes for random and strategic play. However, the strategic player logic was limited to basic box completion. + HW5: Refined the strategic player logic significantly: + Multi-step Decision Making: Implemented a three-step approach for move selection: completing boxes, avoiding chains, and fallback to optimal moves. + Move Evaluation: Added sophisticated cost evaluation (EvaluateMoveCost) and chain detection (DoesMoveCreateChain). + +5. Event-Driven Design + + HW4: The player and board interactions were tightly coupled. + HW5: Introduced event-driven methods (EventAddLine, EventAddBox) to separate game state updates from decision-making logic. This enhances modularity and makes the code easier to extend and debug. + +Learnings + + Modularity and Reusability: Encapsulation of functionality (e.g., board management, player behaviors) allows for better reuse and testing. The separation of concerns between classes improved maintainability. + Polymorphism and Interfaces: Leveraging polymorphism (IPlayer) provided a flexible framework to implement diverse player strategies while ensuring consistency. + Strategic Thinking: Developing a multi-step strategy for players helped refine algorithmic thinking and fostered a deeper understanding of game theory. + RAII and Memory Management: The shift to controlled memory allocation and deallocation in RAII patterns reduced errors and improved reliability. + Event-Driven Programming: Designing the game logic around events encouraged a cleaner architecture and reduced tight coupling. + Iterative Refinement: By analyzing and building upon previous homework, we demonstrated the importance of iterative development and incremental improvement in programming. \ No newline at end of file diff --git a/bar.so b/bar.so deleted file mode 100644 index 2e83e41fb562836b605915be638bc706e09d66d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28392 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 diff --git a/harshit/custom_player.cxx b/harshit/custom_player.cxx deleted file mode 100644 index 9d8eb61..0000000 --- a/harshit/custom_player.cxx +++ /dev/null @@ -1,122 +0,0 @@ -#include "custom_player.h" -#include -#include // for rand -#include // for time -using namespace std; - -// Factory function for dynamic library loading -extern "C" IPlayer* PlayerFactory() { - return new CustomPlayer(); -} - -// Constructor -CustomPlayer::CustomPlayer() { - srand(time(0)); -} - -// Destructor -CustomPlayer::~CustomPlayer() {} - -// Initializes the player with the board size and player symbols -void CustomPlayer::Init(int dots_in_rows, int dots_in_cols, char _player_box, char _player_line) { - board.AllocateBoard(dots_in_rows, dots_in_cols); - player_box = _player_box; - player_line = _player_line; - empty_lines = new Loc[board.GetRows() * board.GetCols()]; -} - -// Cleans up dynamically allocated memory -void CustomPlayer::Close() { - board.FreeBoard(); - delete[] empty_lines; -} - -// Returns the player info -std::string CustomPlayer::PlayerInfo() { - return "Custom Strategic Player"; -} - -// Updates the board when a line is added -void CustomPlayer::EventAddLine(char bar, const Loc& loc) { - board(loc) = bar; -} - -// Updates the board when a box is completed -void CustomPlayer::EventAddBox(char box, const Loc& loc) { - board(loc) = box; -} - -// Updates the list of available line locations -void CustomPlayer::ListEmptyLines() { - empty_lines_count = 0; - for (int r = 0; r < board.GetRows(); r++) { - for (int c = 0; c < board.GetCols(); c++) { - if (board(r, c) == ' ' && Loc(r, c).IsLineLocation()) { - empty_lines[empty_lines_count++] = Loc(r, c); - } - } - } -} - -// Helper function to check if a line completes a box -bool CustomPlayer::DoesLineCompleteBox(const Loc& loc) { - if (loc.IsLineHorizontalLocation()) { - if (loc.row > 0 && board(loc.row - 1, loc.col) != ' ' && - board(loc.row - 1, loc.col - 1) != ' ' && board(loc.row - 1, loc.col + 1) != ' ') - return true; - if (loc.row < board.GetRows() - 1 && board(loc.row + 1, loc.col) != ' ' && - board(loc.row + 1, loc.col - 1) != ' ' && board(loc.row + 1, loc.col + 1) != ' ') - return true; - } else if (loc.IsLineVerticalLocation()) { - if (loc.col > 0 && board(loc.row, loc.col - 1) != ' ' && - board(loc.row - 1, loc.col - 1) != ' ' && board(loc.row + 1, loc.col - 1) != ' ') - return true; - if (loc.col < board.GetCols() - 1 && board(loc.row, loc.col + 1) != ' ' && - board(loc.row - 1, loc.col + 1) != ' ' && board(loc.row + 1, loc.col + 1) != ' ') - return true; - } - return false; -} - -// Helper function to avoid giving the opponent a chance to complete a box -bool CustomPlayer::WouldGiveOpponentBox(const Loc& loc) { - // Temporarily add the line to the board - board(loc) = player_line; - - // Check if the opponent can complete a box in the next move - for (int r = 0; r < board.GetRows(); r++) { - for (int c = 0; c < board.GetCols(); c++) { - if (board(r, c) == ' ' && Loc(r, c).IsLineLocation() && - DoesLineCompleteBox(Loc(r, c))) { - board(loc) = ' '; // Revert the move - return true; - } - } - } - - // Revert the move - board(loc) = ' '; - return false; -} - -// Determines the next move -Loc CustomPlayer::SelectLineLocation() { - ListEmptyLines(); - - // Strategy: Prioritize moves that complete a box - for (int i = 0; i < empty_lines_count; i++) { - if (DoesLineCompleteBox(empty_lines[i])) { - return empty_lines[i]; - } - } - - // Avoid moves that give the opponent a chance to complete a box - for (int i = 0; i < empty_lines_count; i++) { - if (!WouldGiveOpponentBox(empty_lines[i])) { - return empty_lines[i]; - } - } - - // Otherwise, pick a random move - return empty_lines[rand() % empty_lines_count]; -} \ No newline at end of file diff --git a/harshit/custom_player.h b/harshit/custom_player.h deleted file mode 100644 index f617333..0000000 --- a/harshit/custom_player.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __CUSTOM_PLAYER__ -#define __CUSTOM_PLAYER__ - -#include "player.h" -#include "common.h" -#include "board.h" -#include -#include - -class CustomPlayer : public IPlayer { -private: - Board board; // Game board to track state - char player_box; // Character representing the player's boxes - char player_line; // Character representing the player's lines - Loc* empty_lines; // Array to store available line locations - int empty_lines_count; // Number of available line locations - -public: - CustomPlayer(); - ~CustomPlayer(); - - // Initializes the player with board details and player symbols - void Init(int dots_in_rows, int dots_in_cols, char player_box, char player_line) override; - - // Cleans up dynamically allocated memory - void Close() override; - - // Returns the player information - std::string PlayerInfo() override; - - // Called when a line is added to the board - void EventAddLine(char bar, const Loc& loc) override; - - // Called when a box is completed on the board - void EventAddBox(char box, const Loc& loc) override; - - // Determines the next move based on the current state of the board - Loc SelectLineLocation() override; - -private: - // Updates the list of available line locations - void ListEmptyLines(); - - // Helper function to check if a line completes a box - bool DoesLineCompleteBox(const Loc& loc); - - // Helper function to avoid giving the opponent a chance to complete a box - bool WouldGiveOpponentBox(const Loc& loc); - - // Evaluate the best line location strategically - Loc GetBestStrategicMove(); -}; - -#endif \ No newline at end of file diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 215f01e..0000000 --- a/readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -Build mazerunner program and player_randommove.so library - -g++ -ansi -pedantic -std=c++14 board.cxx dotsboxesgm.cxx main.cxx -o dotsboxes -g++ -shared -fPIC -ansi -pedantic -std=c++14 random_player.cxx board.cxx -o random_player.so - - -playing the dots and boxes games with multiple players - -./dotsboxes ./strategic_player.so ./random_player.so ./strategic_player.so ./random_player.so - diff --git a/strategic_player1.cxx b/ss.cxx similarity index 94% rename from strategic_player1.cxx rename to ss.cxx index 79bc139..379970a 100644 --- a/strategic_player1.cxx +++ b/ss.cxx @@ -1,4 +1,17 @@ -#include "strategic_player1.h" +// Team member 1 +// Name: Sandipsinh Rathod +// Email: sdr5549@psu.edu +// Team member 2 +// Name: Sapan Shah +// Email: scs6041@psu.edu +// +// Program homework 5 +// Class: CMPSC 330 +// Current Date: 6/12/24 9:15 PM +// Due Date: 6/12/24 11:59 PM + + +#include "ss.h" extern "C" IPlayer *PlayerFactory() { return new StrategicPlayer1(); diff --git a/strategic_player1.h b/ss.h similarity index 100% rename from strategic_player1.h rename to ss.h diff --git a/strategic_player.cxx b/strategic_player.cxx deleted file mode 100644 index e734ba3..0000000 --- a/strategic_player.cxx +++ /dev/null @@ -1,171 +0,0 @@ -#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); -} diff --git a/strategic_player.h b/strategic_player.h deleted file mode 100644 index 5ece82e..0000000 --- a/strategic_player.h +++ /dev/null @@ -1,38 +0,0 @@ - -#ifndef HW4_STRATEGIC_PLAYER_H -#define HW4_STRATEGIC_PLAYER_H - -#include "common.h" -#include "board.h" -#include "player.h" - -class StrategicPlayer: public IPlayer { - char name; - char box_name; - - Board board; -public: - string PlayerInfo(); - // Init(const int,const int) will be called before playing the game - // You can create your own data-structure - void Init - ( int board_rows // the size of board (including dots, lines, and boxes) - , int board_cols // the size of board (including dots, lines, and boxes) - , char box_type // the character for the player's boxes - , char line_type // the character for the player's lines - ); - // Close() will be called after finishing playing the game - // You can remove all dynamically allocated memories - void Close(); - // EventAddLine() and EventAddBox() will be called - // when a player adds a line or when a system assign a box's owner - void EventAddLine(char bar, const Loc& loc); - void EventAddBox (char box, const Loc& loc); - // Loc SelectLineLocation() will be called - // when the game system ask where your player want to add a line - Loc SelectLineLocation(); - - ~StrategicPlayer(); -}; - -#endif //HW4_STRATEGIC_PLAYER_H