add better method

This commit is contained in:
Sandipsinh Rathod 2024-12-06 20:40:19 -05:00
parent 6362853abd
commit db8e2596ef
No known key found for this signature in database
2 changed files with 60 additions and 31 deletions

@ -1,19 +1,13 @@
#include <iostream>
#include <limits>
#include "strategic_player1.h" #include "strategic_player1.h"
#include "common.h"
extern "C" IPlayer* PlayerFactory() extern "C" IPlayer *PlayerFactory() {
{
return new StrategicPlayer1(); return new StrategicPlayer1();
} }
using namespace std; using namespace std;
string StrategicPlayer1::PlayerInfo() { string StrategicPlayer1::PlayerInfo() {
return "Big MAN Smol PP"; return "Sandipsinh Rathod (sdr5549@psu.edu), Sapan Shah (scs6041@psu.edu)";
} }
void StrategicPlayer1::Init(int board_rows, int board_cols, char box_type, char line_type) { void StrategicPlayer1::Init(int board_rows, int board_cols, char box_type, char line_type) {
@ -37,48 +31,64 @@ void StrategicPlayer1::EventAddBox(char box, const Loc& loc) {
} }
Loc StrategicPlayer1::SelectLineLocation() { Loc StrategicPlayer1::SelectLineLocation() {
Loc box_completing_move = FindBoxCompletingMove(); vector<Loc> empty_lines;
if (box_completing_move.row != -1 && box_completing_move.col != -1) { ListEmptyLines(empty_lines);
return box_completing_move; // Prioritize moves that complete a box
// Step 1: Look for a move to complete a box
Loc move = FindBoxCompletingMove();
if (move.row != -1) {
return move;
} }
return FindOptimalMove(); // Fall back to a heuristic-based optimal move // Step 2: Force opponent into bad moves
move = ForceOpponentMistake(empty_lines);
if (move.row != -1) {
return move;
}
// Step 3: Fall back to the optimal move
return FindOptimalMove();
} }
StrategicPlayer1::~StrategicPlayer1() { StrategicPlayer1::~StrategicPlayer1() {
Close(); Close();
} }
// Private helper functions
Loc StrategicPlayer1::FindBoxCompletingMove() { Loc StrategicPlayer1::FindBoxCompletingMove() {
vector<Loc> empty_lines; vector<Loc> empty_lines;
ListEmptyLines(empty_lines); ListEmptyLines(empty_lines);
for (const Loc &loc: empty_lines) { for (const Loc &loc: empty_lines) {
int row = loc.row, col = loc.col; int row = loc.row, col = loc.col;
// Check if adding a line at this location completes a box
if ((row % 2 == 0 && col % 2 == 1) || (row % 2 == 1 && col % 2 == 0)) {
if (DoesMoveCompleteBox(row, col)) { if (DoesMoveCompleteBox(row, col)) {
return loc; // Return the first box-completing move found return loc;
}
} }
} }
return Loc(-1, -1); // No box-completing move found return Loc(-1, -1);
} }
bool StrategicPlayer1::DoesMoveCompleteBox(int row, int col) { bool StrategicPlayer1::DoesMoveCompleteBox(int row, int col) {
// Check adjacent boxes based on the move's orientation
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
return (CountBoxLines(row - 1, col) == 3 || CountBoxLines(row + 1, col) == 3); return (CountBoxLines(row - 1, col) == 3 || CountBoxLines(row + 1, col) == 3);
} else if (row % 2 == 1 && col % 2 == 0) { // Vertical line } else if (row % 2 == 1 && col % 2 == 0) { // Vertical line
return (CountBoxLines(row, col - 1) == 3 || CountBoxLines(row, col + 1) == 3); return (CountBoxLines(row, col - 1) == 3 || CountBoxLines(row, col + 1) == 3);
} }
return false; return false;
} }
Loc StrategicPlayer1::ForceOpponentMistake(const vector<Loc> &empty_lines) {
Loc best_move(-1, -1);
for (const Loc &loc: empty_lines) {
if (!DoesMoveCreateChain(loc.row, loc.col)) {
return loc; // Choose the first safe move
}
}
return best_move;
}
Loc StrategicPlayer1::FindOptimalMove() { Loc StrategicPlayer1::FindOptimalMove() {
vector<Loc> empty_lines; vector<Loc> empty_lines;
ListEmptyLines(empty_lines); ListEmptyLines(empty_lines);
@ -97,10 +107,28 @@ Loc StrategicPlayer1::FindOptimalMove() {
return best_move; return best_move;
} }
bool StrategicPlayer1::DoesMoveCreateChain(int row, int col) {
board(row, col) = name;
bool creates_chain = false;
if (row % 2 == 0 && col % 2 == 1) {
if (CountBoxLines(row - 1, col) == 2 || CountBoxLines(row + 1, col) == 2) {
creates_chain = true;
}
} else if (row % 2 == 1 && col % 2 == 0) {
if (CountBoxLines(row, col - 1) == 2 || CountBoxLines(row, col + 1) == 2) {
creates_chain = true;
}
}
board(row, col) = ' ';
return creates_chain;
}
int StrategicPlayer1::EvaluateMoveCost(int row, int col) { int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
int cost = 0; int cost = 0;
// Evaluate the "cost" of the move by summing the number of sides completed for adjacent boxes
if (row % 2 == 0 && col % 2 == 1) { // Horizontal line if (row % 2 == 0 && col % 2 == 1) { // Horizontal line
cost += CountBoxLines(row - 1, col); cost += CountBoxLines(row - 1, col);
cost += CountBoxLines(row + 1, col); cost += CountBoxLines(row + 1, col);
@ -113,13 +141,11 @@ int StrategicPlayer1::EvaluateMoveCost(int row, int col) {
} }
int StrategicPlayer1::CountBoxLines(int row, int col) { int StrategicPlayer1::CountBoxLines(int row, int col) {
// Ensure the location is within bounds
if (row < 0 || row >= board.GetRows() || col < 0 || col >= board.GetCols()) { if (row < 0 || row >= board.GetRows() || col < 0 || col >= board.GetCols()) {
return 0; return 0;
} }
int count = 0; int count = 0;
// Check all four sides of the box
if (board(row - 1, col) != ' ') count++; // Top if (board(row - 1, col) != ' ') count++; // Top
if (board(row + 1, col) != ' ') count++; // Bottom if (board(row + 1, col) != ' ') count++; // Bottom
if (board(row, col - 1) != ' ') count++; // Left if (board(row, col - 1) != ' ') count++; // Left
@ -133,7 +159,7 @@ void StrategicPlayer1::ListEmptyLines(vector<Loc>& empty_lines) {
for (int c = 0; c < board.GetCols(); c++) { for (int c = 0; c < board.GetCols(); c++) {
Loc loc(r, c); Loc loc(r, c);
if (loc.IsLineLocation() && board(r, c) == ' ') { if (loc.IsLineLocation() && board(r, c) == ' ') {
empty_lines.push_back(loc); // Add all empty line locations to the list empty_lines.push_back(loc);
} }
} }
} }

@ -5,6 +5,7 @@
#include "board.h" #include "board.h"
#include "player.h" #include "player.h"
#include <vector> #include <vector>
#include <limits>
class StrategicPlayer1 : public IPlayer { class StrategicPlayer1 : public IPlayer {
char name; char name;
@ -26,6 +27,8 @@ public:
void ListEmptyLines(vector<Loc>& empty_lines); void ListEmptyLines(vector<Loc>& empty_lines);
bool DoesMoveCompleteBox(int row, int col); bool DoesMoveCompleteBox(int row, int col);
Loc FindBoxCompletingMove(); Loc FindBoxCompletingMove();
bool DoesMoveCreateChain(int row, int col);
Loc ForceOpponentMistake(const vector<Loc>& empty_lines);
~StrategicPlayer1(); ~StrategicPlayer1();
}; };