Skip to content

Commit

Permalink
Merge pull request #5 from N1ckn1ght/dev-1.1
Browse files Browse the repository at this point in the history
Full code rework
  • Loading branch information
N1ckn1ght authored Jan 20, 2023
2 parents a6daf1f + e02a75a commit b398e98
Show file tree
Hide file tree
Showing 31 changed files with 1,292 additions and 967 deletions.
11 changes: 0 additions & 11 deletions Cell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,4 @@ Cell nextCell(const Cell cell)
return Cell::Cross;
}
return Cell::Empty;
}

Cell wonCell(const Cell cell)
{
if (cell == Cell::Cross) {
return Cell::Cwon;
}
if (cell == Cell::Null) {
return Cell::Nwon;
}
return Cell::Any;
}
7 changes: 2 additions & 5 deletions Cell.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ enum class Cell {
Cross,
Null,
Empty,
Any, // this is for draw scenario
Cwon, // this is for scenario of a won board as cross
Nwon // this is for scenario of a won board as nulls
Any
};

extern Cell nextCell(const Cell cell);
extern Cell wonCell(const Cell cell);
extern Cell nextCell(const Cell cell);
5 changes: 5 additions & 0 deletions Coord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ Coord::Coord(size_t y_, size_t x_)
{
y = y_;
x = x_;
}

bool operator == (const Coord &lhs, const Coord &rhs)
{
return (lhs.y == rhs.y && lhs.x == rhs.x);
}
3 changes: 3 additions & 0 deletions Coord.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#pragma once
#include "GlobalCoord.h"

class Coord {
public:
size_t y;
size_t x;

Coord(size_t y_ = -1, size_t x_ = -1);

friend bool operator == (const Coord& lhs, const Coord& rhs);
};
109 changes: 109 additions & 0 deletions EdgeBot_v1_0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "EdgeBot_v1_0.h"

EdgeBot_v1_0::EdgeBot_v1_0()
{
EVAL_MAX = 255;

// Points for a cell on a local board
// Note: it has unintented, but interesting asymmetric realisation at string 47
// (localPts[y][bx] used, instead of localPts[y][x] expected)
localPts = std::vector <std::vector <double>>({ {3, 2, 3}, {2, 4, 2}, {3, 2, 3} });
// Multiplier of points for a cell on a local board on the global board
globalPts = std::vector <std::vector <double>>({ {1.5, 1, 1.5}, {1, 2, 1}, {1.5, 1, 1.5} });
// Points for a board on the global board
localWinPts = std::vector <std::vector <double>>({ {32, 32, 32}, {32, 32, 32}, {32, 32, 32} });
// Points for winning the game
globalWinPts = 65535;
// Points for having an attack on a local board (e.g. [XX.] or [X.X])
localAtkPts = 5;
// Limit for points for attack on a local board
localAtkLim = 12;
// Points for having an attack on the global board (winning two board in row, like [OO.] or [O.O])
globalAtkPts = 48;
// Points for having a self-referencing cell, meaning it's on (i, j, i, j) coordinates
selfRefPts = 3;
}

double EdgeBot_v1_0::staticEval(Field& field)
{
// checks for: globalWinPts
switch (field.getWinner()) {
case Cell::Cross:
return globalWinPts;
case Cell::Null:
return -globalWinPts;
case Cell::Any:
return 0;
default:
break;
}
// checks for: localPts, globalPts, localWinPts, selfRefPts
double result = 0;
for (size_t by = 0; by < 3; by++) {
for (size_t bx = 0; bx < 3; bx++) {
result += selfRefPts * k(field.get(by, bx, by, bx));
result += localWinPts[by][bx] * k(field.getWinner(by, bx));
for (size_t y = 0; y < 3; y++) {
for (size_t x = 0; x < 3; x++) {
result += globalPts[by][bx] * localPts[y][bx] * k(field.get(by, bx, y, x));
}
}
}
}
// checks for: globalAtkPts
for (size_t i = 0; i < 3; i++) {
result += double(std::abs(k(field.getWinner(i, 0)) + k(field.getWinner(i, 1)) + k(field.getWinner(i, 2))) == 2) * k(field.getWinner(i, 0)) * globalAtkPts;
result += double(std::abs(k(field.getWinner(0, i)) + k(field.getWinner(1, i)) + k(field.getWinner(2, i))) == 2) * k(field.getWinner(0, i)) * globalAtkPts;
}
result += double(std::abs(k(field.getWinner(0, 0)) + k(field.getWinner(1, 1)) + k(field.getWinner(2, 2))) == 2) * k(field.getWinner(1, 1)) * globalAtkPts;
result += double(std::abs(k(field.getWinner(0, 2)) + k(field.getWinner(1, 1)) + k(field.getWinner(2, 0))) == 2) * k(field.getWinner(1, 1)) * globalAtkPts;
// checks for: localAtkPts, localAtkLim
double temp = 0;
for (size_t by = 0; by < 3; by++) {
for (size_t bx = 0; bx < 3; bx++) {
for (size_t i = 0; i < 3; i++) {
temp += (double)atk(field.get(by, bx, i, 0), field.get(by, bx, i, 1), field.get(by, bx, i, 2)) * localAtkPts;
temp += (double)atk(field.get(by, bx, 0, i), field.get(by, bx, 1, i), field.get(by, bx, 2, i)) * localAtkPts;
}
temp += (double)atk(field.get(by, bx, 0, 0), field.get(by, bx, 1, 1), field.get(by, bx, 2, 2)) * localAtkPts;
temp += (double)atk(field.get(by, bx, 0, 2), field.get(by, bx, 1, 1), field.get(by, bx, 2, 0)) * localAtkPts;
result += std::min(std::max(temp, -localAtkLim), localAtkLim);
}
}
return result;
}

void EdgeBot_v1_0::modEvals(std::vector<EvalMove>& evals)
{
for (EvalMove& eval : evals) {
eval.eval = std::min(std::max(eval.eval, -EVAL_MAX), EVAL_MAX);
}
}

int EdgeBot_v1_0::k(const Cell& cell) const
{
switch (cell) {
case Cell::Empty:
return 0;
case Cell::Cross:
return 1;
case Cell::Null:
return -1;
case Cell::Any:
return 0;
default:
return 0;
}
}

int EdgeBot_v1_0::atk(const Cell& a, const Cell& b, const Cell& c) const
{
int v = k(a) + k(b) + k(c);
if (v == 2) {
return 1;
}
if (v == -2) {
return -1;
}
return 0;
}
26 changes: 26 additions & 0 deletions EdgeBot_v1_0.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include "MinMaxEngine.h"

class EdgeBot_v1_0 : public MinMaxEngine
{
private:
double EVAL_MAX;

// pure static evaluation variables go here:
std::vector <std::vector <double>> localPts;
std::vector <std::vector <double>> globalPts;
std::vector <std::vector <double>> localWinPts;
double globalWinPts;
double localAtkPts;
double localAtkLim;
double globalAtkPts;
double selfRefPts;

void modEvals(std::vector <EvalMove>& evals) override;
double staticEval(Field& field) override;

int k(const Cell& cell) const;
int atk(const Cell& a, const Cell& b, const Cell& c) const;
public:
EdgeBot_v1_0();
};
122 changes: 122 additions & 0 deletions EdgeBot_v1_1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "EdgeBot_v1_1.h"

EdgeBot_v1_1::EdgeBot_v1_1()
{
EVAL_MAX = 255;

// Points for a cell on a local board
localPts = std::vector <std::vector <double>>({ {0.3, 0.2, 0.3}, {0.2, 0.4, 0.2}, {0.3, 0.2, 0.3} });
// Multiplier for a cell on a local board on the global board
globalPts = std::vector <std::vector <double>>({ {1.5, 1, 1.5}, {1, 2, 1}, {1.5, 1, 1.5} });
// Points for a board on the global board
localWinPts = std::vector <std::vector <double>>({ {5, 3, 5}, {3, 6, 3}, {5, 3, 5} });
// Points for winning the game
globalWinPts = 255;
// Points for having an attack on a local board (e.g. [XX.] or [X.X]), doesn't stack
localAtkPts = 0.5;
// Points (-penalty) for having more then 3 boards with enemy cells referring to a winning board
wastedAtkPts = 0;
// Points for having an attack on the global board (winning two board in row, like [OO.] or [O.O])
globalAtkPts = 6;
// Points for having a self-referencing cell, meaning it's on (i, j, i, j) coordinates
selfRefPts = 0.3;
}

double EdgeBot_v1_1::staticEval(Field& field)
{
// checks for: globalWinPts
switch (field.getWinner()) {
case Cell::Cross:
return globalWinPts;
case Cell::Null:
return -globalWinPts;
case Cell::Any:
return 0;
default:
break;
}
// checks for: localWinPts, selfRefPts
double result = 0;
for (size_t by = 0; by < 3; by++) {
for (size_t bx = 0; bx < 3; bx++) {
double temp = localWinPts[by][bx] * k(field.getWinner(by, bx));
if (temp != 0) {
result += temp;
continue;
}
result += selfRefPts * k(field.get(by, bx, by, bx));
for (size_t y = 0; y < 3; y++) {
for (size_t x = 0; x < 3; x++) {
result += k(field.get(by, bx, y, x)) * globalPts[by][bx] * localPts[y][x];
}
}
}
}
// checks for: globalAtkPts
for (size_t i = 0; i < 3; i++) {
result += double(std::abs(k(field.getWinner(i, 0)) + k(field.getWinner(i, 1)) + k(field.getWinner(i, 2))) == 2) * k(field.getWinner(i, 0)) * globalAtkPts;
result += double(std::abs(k(field.getWinner(0, i)) + k(field.getWinner(1, i)) + k(field.getWinner(2, i))) == 2) * k(field.getWinner(0, i)) * globalAtkPts;
}
result += double(std::abs(k(field.getWinner(0, 0)) + k(field.getWinner(1, 1)) + k(field.getWinner(2, 2))) == 2) * k(field.getWinner(1, 1)) * globalAtkPts;
result += double(std::abs(k(field.getWinner(0, 2)) + k(field.getWinner(1, 1)) + k(field.getWinner(2, 0))) == 2) * k(field.getWinner(1, 1)) * globalAtkPts;
// checks for: localAtkPts, wastedAtkPts
int temp = 0;
for (size_t by = 0; by < 3; by++) {
for (size_t bx = 0; bx < 3; bx++) {
for (size_t i = 0; i < 3; i++) {
temp += atk(field.get(by, bx, i, 0), field.get(by, bx, i, 1), field.get(by, bx, i, 2));
temp += atk(field.get(by, bx, 0, i), field.get(by, bx, 1, i), field.get(by, bx, 2, i));
}
temp += atk(field.get(by, bx, 0, 0), field.get(by, bx, 1, 1), field.get(by, bx, 2, 2));
temp += atk(field.get(by, bx, 0, 2), field.get(by, bx, 1, 1), field.get(by, bx, 2, 0));
if (temp > 0) {
if (temp > 1) {
result += wastedAtkPts;
}
result += localAtkPts;
}
else if (temp < 0) {
if (temp < 1) {
result -= wastedAtkPts;
}
result -= localAtkPts;
}
}
}
return result;
}

void EdgeBot_v1_1::modEvals(std::vector<EvalMove>& evals)
{
for (EvalMove& eval : evals) {
eval.eval = std::min(std::max(eval.eval, -EVAL_MAX), EVAL_MAX);
}
}

int EdgeBot_v1_1::k(const Cell& cell) const
{
switch (cell) {
case Cell::Empty:
return 0;
case Cell::Cross:
return 1;
case Cell::Null:
return -1;
case Cell::Any:
return 0;
default:
return 0;
}
}

int EdgeBot_v1_1::atk(const Cell& a, const Cell& b, const Cell& c) const
{
int v = k(a) + k(b) + k(c);
if (v == 2) {
return 1;
}
if (v == -2) {
return -1;
}
return 0;
}
26 changes: 26 additions & 0 deletions EdgeBot_v1_1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include "MinMaxEngine.h"

class EdgeBot_v1_1 : public MinMaxEngine
{
private:
double EVAL_MAX;

// pure static evaluation variables go here:
std::vector <std::vector <double>> localPts;
std::vector <std::vector <double>> globalPts;
std::vector <std::vector <double>> localWinPts;
double globalWinPts;
double localAtkPts;
double globalAtkPts;
double wastedAtkPts;
double selfRefPts;

void modEvals(std::vector <EvalMove>& evals) override;
double staticEval(Field& field) override;

int k(const Cell& cell) const;
int atk(const Cell& a, const Cell& b, const Cell& c) const;
public:
EdgeBot_v1_1();
};
Loading

0 comments on commit b398e98

Please sign in to comment.