Skip to content

Commit

Permalink
Merge pull request #1107 from Jazeem:ntuple
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 564440542
Change-Id: Ibe5797caaa46c997126c26bdb4295f34a20c756f
  • Loading branch information
lanctot committed Sep 12, 2023
2 parents 63b430c + 91f43a6 commit 2847cef
Show file tree
Hide file tree
Showing 5 changed files with 517 additions and 755 deletions.
34 changes: 31 additions & 3 deletions open_spiel/games/twenty_forty_eight/2048.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ namespace open_spiel {
namespace twenty_forty_eight {
namespace {

enum Move { kMoveUp = 0, kMoveRight = 1, kMoveDown = 2, kMoveLeft = 3 };

constexpr std::array<Action, 4> kPlayerActions = {kMoveUp, kMoveRight,
kMoveDown, kMoveLeft};

Expand Down Expand Up @@ -228,6 +226,29 @@ void TwentyFortyEightState::DoApplyAction(Action action) {
total_actions_++;
}

bool TwentyFortyEightState::DoesActionChangeBoard(Action action) const {
const std::array<std::array<int, 4>, 2>& traversals = kTraversals[action];
for (int r : traversals[0]) {
for (int c : traversals[1]) {
int tile = GetCellContent(r, c);
if (tile > 0) {
std::array<Coordinate, 2> positions =
FindFarthestPosition(r, c, action);
Coordinate farthest_pos = positions[0];
Coordinate next_pos = positions[1];
int next_cell = GetCellContent(next_pos.row, next_pos.column);
if (next_cell > 0 && next_cell == tile &&
!BoardAt(next_pos).is_merged) {
return true;
} else if (farthest_pos.row != r || farthest_pos.column != c) {
return true;
}
}
}
}
return false;
}

std::string TwentyFortyEightState::ActionToString(Player player,
Action action_id) const {
if (player == kChancePlayerId) {
Expand Down Expand Up @@ -295,7 +316,14 @@ std::vector<Action> TwentyFortyEightState::LegalActions() const {
}

// Construct a vector from the array.
return std::vector<Action>(kPlayerActions.begin(), kPlayerActions.end());
std::vector<Action> actions =
std::vector<Action>(kPlayerActions.begin(), kPlayerActions.end());

std::vector<Action> actions_allowed = {};
for (Action action : actions) {
if (DoesActionChangeBoard(action)) actions_allowed.push_back(action);
}
return actions_allowed;
}

std::string TwentyFortyEightState::ToString() const {
Expand Down
3 changes: 3 additions & 0 deletions open_spiel/games/twenty_forty_eight/2048.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
namespace open_spiel {
namespace twenty_forty_eight {

enum Move { kMoveUp = 0, kMoveRight = 1, kMoveDown = 2, kMoveLeft = 3 };

constexpr int kNumPlayers = 1;
constexpr int kRows = 4;
constexpr int kColumns = 4;
Expand Down Expand Up @@ -124,6 +126,7 @@ class TwentyFortyEightState : public State {
bool TileMatchesAvailable() const;
void PrepareTiles();
int GetCellContent(int r, int c) const;
bool DoesActionChangeBoard(Action action) const;

const TwentyFortyEightGame& parent_game_;
Player current_player_ = kChancePlayerId;
Expand Down
23 changes: 7 additions & 16 deletions open_spiel/games/twenty_forty_eight/2048_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "open_spiel/games/twenty_forty_eight/2048.h"

#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"
#include "open_spiel/tests/basic_tests.h"

namespace open_spiel {
Expand Down Expand Up @@ -62,7 +63,7 @@ void MultipleMergePossibleTest() {
TwentyFortyEightState* cstate =
static_cast<TwentyFortyEightState*>(state.get());
cstate->SetCustomBoard({0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0});
cstate->ApplyAction(cstate->LegalActions()[2]);
cstate->ApplyAction(kMoveDown);
SPIEL_CHECK_EQ(cstate->BoardAt(3, 0).value, 4);
}

Expand All @@ -78,7 +79,7 @@ void OneMergePerTurnTest() {
TwentyFortyEightState* cstate =
static_cast<TwentyFortyEightState*>(state.get());
cstate->SetCustomBoard({2, 4, 0, 4, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0});
cstate->ApplyAction(cstate->LegalActions()[2]);
cstate->ApplyAction(kMoveDown);
SPIEL_CHECK_EQ(cstate->BoardAt(2, 1).value, 4);
SPIEL_CHECK_EQ(cstate->BoardAt(3, 1).value, 4);
}
Expand Down Expand Up @@ -112,7 +113,7 @@ void GameWonTest() {
static_cast<TwentyFortyEightState*>(state.get());
cstate->SetCustomBoard(
{4, 8, 2, 4, 2, 4, 8, 16, 1024, 128, 64, 128, 1024, 8, 2, 8});
cstate->ApplyAction(cstate->LegalActions()[2]);
cstate->ApplyAction(kMoveDown);
SPIEL_CHECK_EQ(cstate->IsTerminal(), true);
SPIEL_CHECK_EQ(cstate->Returns()[0], 2048);
}
Expand All @@ -122,26 +123,16 @@ void GameWonTest() {
// 0 0 0 0
// 0 0 0 0
// 2 0 0 2
// No random tiles should appear if the board didn't change after player move
// Down should not be a legal action here as it does not change the board
void BoardNotChangedTest() {
std::shared_ptr<const Game> game = LoadGame("2048");
std::unique_ptr<State> state = game->NewInitialState();
TwentyFortyEightState* cstate =
static_cast<TwentyFortyEightState*>(state.get());
cstate->SetCustomBoard({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2});
cstate->ApplyAction(cstate->LegalActions()[2]);
// Check the board remained the same after player move
for (int r = 0; r < kRows; r++) {
for (int c = 0; c < kColumns; c++) {
if (!(r == 3 && c == 0) && !(r == 3 || c == 3)) {
SPIEL_CHECK_EQ(cstate->BoardAt(r, c).value, 0);
}
}
for (Action action : cstate->LegalActions()) {
SPIEL_CHECK_NE(action, kMoveDown);
}
SPIEL_CHECK_EQ(cstate->BoardAt(3, 0).value, 2);
SPIEL_CHECK_EQ(cstate->BoardAt(3, 3).value, 2);
// Check move didn't go to random player since board didn't change
SPIEL_CHECK_EQ(cstate->CurrentPlayer(), 0);
}

} // namespace
Expand Down
Loading

0 comments on commit 2847cef

Please sign in to comment.