Skip to content

Commit

Permalink
perfect: Support move randomly
Browse files Browse the repository at this point in the history
This commit introduces significant changes to the allMaxBy function in
perfect_player.cpp. The updated logic now prioritizes moves based on their
expected outcomes, specifically focusing on "Win" ('W'), "Draw" ('D'), and
"Loss" ('L') scenarios.

Key changes include:
- Added conditions to check the first character of the string returned by
  the toString method of each evaluated move.
- The function now first looks for moves leading to a win ('W'). If any are
  found, only these moves are considered.
- If no winning moves ('W') are found, the function then looks for draws ('D').
  Only draw moves are considered in this case.
- If neither winning nor drawing moves are found, the function defaults to
  considering loss ('L') moves.
- The previous implementation based on comparing values has been retained
  under an else clause, ensuring backward compatibility when shuffling is not
  enabled.

This enhancement aligns the move selection process more closely with strategic
gameplay considerations, improving the PerfectPlayer's decision-making
capabilities.

Change-Id: Iad135da3856a0b5acc3a16c35e1c22dcfb5c21ed
  • Loading branch information
calcitem committed Dec 24, 2023
1 parent 2dd72a0 commit 5b065a0
Showing 1 changed file with 64 additions and 9 deletions.
73 changes: 64 additions & 9 deletions src/perfect/perfect_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include <string>
#include <vector>

#include "option.h"

class GameState;

std::map<Wrappers::WID, Wrappers::WSector> Sectors::sectors;
Expand Down Expand Up @@ -345,20 +347,49 @@ std::vector<T> PerfectPlayer::allMaxBy(std::function<K(T)> f,
const std::vector<T> &l, K minValue)
{
std::vector<T> r;
K ma = minValue;
for (auto &m : l) {
K e = f(m);
if (e > ma) {
ma = e;
r.clear();
r.push_back(m);
} else if (e == ma) {
r.push_back(m);

if (gameOptions.getShufflingEnabled()) {
bool foundW = false;
bool foundD = false;

for (auto &m : l) {
K e = f(m);
std::string eStr = e.toString();

if (eStr[0] == 'W') {
if (!foundW) {
r.clear();
foundW = true;
}
r.push_back(m);
} else if (!foundW && eStr[0] != 'L') {
if (!foundD) {
r.clear();
foundD = true;
}
r.push_back(m);
} else if (!foundW && !foundD && eStr[0] == 'L') {
r.push_back(m);
}
}
} else {
K ma = minValue;
for (auto &m : l) {
K e = f(m);
if (e > ma) {
ma = e;
r.clear();
r.push_back(m);
} else if (e == ma) {
r.push_back(m);
}
}
}

return r;
}

#if 1
// Assuming the definition of gui_eval_elem2::min_value function
std::vector<AdvancedMove> PerfectPlayer::goodMoves(const GameState &s)
{
Expand All @@ -367,6 +398,30 @@ std::vector<AdvancedMove> PerfectPlayer::goodMoves(const GameState &s)
getMoveList(s),
Wrappers::gui_eval_elem2::min_value(getSec(s)));
}
#else
std::vector<AdvancedMove> PerfectPlayer::goodMoves(const GameState &s)
{
auto moveList = getMoveList(s);
std::cout << "Move list size: " << moveList.size()
<< std::endl;
std::function<Wrappers::gui_eval_elem2(AdvancedMove)> evalFunction =
[this, &s](AdvancedMove m) {
auto value = moveValue(s, m);
std::cout << "Evaluating move from " << m.from << " to " << m.to
<< " with score: " << value.toString()
<< std::endl;
return value;
};
auto bestMoves = allMaxBy(evalFunction, moveList,
Wrappers::gui_eval_elem2::min_value(getSec(s)));
std::cout << "Number of best moves: " << bestMoves.size() << std::endl;
return bestMoves;
}
#endif

int PerfectPlayer::NGMAfterMove(const GameState &s, AdvancedMove &m)
{
Expand Down

0 comments on commit 5b065a0

Please sign in to comment.