Skip to content

Commit

Permalink
change rbc sense to behave like APL's sense rules
Browse files Browse the repository at this point in the history
  • Loading branch information
acxz committed Apr 21, 2022
1 parent 0c265fb commit 0e6ff72
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 26 deletions.
32 changes: 18 additions & 14 deletions open_spiel/games/rbc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,14 @@ chess::ObservationTable ComputeObservationTable(const chess::ChessBoard& board,
if (sense_location < 0) return observability_table;

// All pieces under the sense window.
int inner_size = board_size - sense_size + 1;
chess::Square sense_sq = chess::IndexToSquare(sense_location, inner_size);
SPIEL_DCHECK_LE(sense_sq.x + sense_size, board_size);
SPIEL_DCHECK_LE(sense_sq.y + sense_size, board_size);
for (int8_t x = sense_sq.x; x < sense_sq.x + sense_size; ++x) {
for (int8_t y = sense_sq.y; y < sense_sq.y + sense_size; ++y) {
chess::Square sense_sq = chess::IndexToSquare(sense_location, board_size);
// Find min and max bounds for the sense window
int8_t left_sense_sq_x = std::min(sense_sq.x - sense_size/2, 0);
int8_t right_sense_sq_x = std::max(sense_sq.x + sense_size/2, board_size);
int8_t bottom_sense_sq_y = std::min(sense_sq.y - sense_size/2, 0);
int8_t top_sense_sq_y = std::max(sense_sq.y + sense_size/2, board_size);
for (int8_t x = left_sense_sq_x; x < right_sense_sq_x; ++x) {
for (int8_t y = bottom_sense_sq_y; y < top_sense_sq_y; ++y) {
const chess::Square sq{x, y};
size_t index = chess::SquareToIndex(sq, board_size);
observability_table[index] = true;
Expand Down Expand Up @@ -238,17 +240,19 @@ class RbcObserver : public Observer {
const std::string type_string = chess::PieceTypeToString(
piece_type, /*uppercase=*/color == chess::Color::kWhite);
const int board_size = board.BoardSize();
int inner_size = board_size - sense_size + 1;
chess::Square sense_square =
chess::IndexToSquare(sense_location, inner_size);
chess::IndexToSquare(sense_location, board_size);
auto out = allocator->Get(prefix + "_" + type_string + "_pieces",
{board_size, board_size});

if (sense_location < 0) return; // No sense window specified.
SPIEL_DCHECK_LE(sense_square.x + sense_size, board_size);
SPIEL_DCHECK_LE(sense_square.y + sense_size, board_size);
for (int8_t x = sense_square.x; x < sense_square.x + sense_size; ++x) {
for (int8_t y = sense_square.y; y < sense_square.y + sense_size; ++y) {
// Find min and max bounds for the sense window
int8_t left_sense_sq_x = std::min(sense_sq.x - sense_size/2, 0);
int8_t right_sense_sq_x = std::max(sense_sq.x + sense_size/2, board_size);
int8_t bottom_sense_sq_y = std::min(sense_sq.y - sense_size/2, 0);
int8_t top_sense_sq_y = std::max(sense_sq.y + sense_size/2, board_size);
for (int8_t x = left_sense_sq_x; x < right_sense_sq_x; ++x) {
for (int8_t y = bottom_sense_sq_y; y < top_sense_sq_y; ++y) {
const chess::Square square{x, y};
const chess::Piece& piece_on_board = board.at(square);
const bool write_square =
Expand Down Expand Up @@ -419,7 +423,7 @@ void RbcState::MaybeGenerateLegalActions() const {

if (phase_ == MovePhase::kSensing) {
int num_possible_sense_locations =
game()->inner_size() * game()->inner_size();
game()->board_size() * game()->board_size();
cached_legal_actions_->resize(num_possible_sense_locations);
absl::c_iota(*cached_legal_actions_, 0);
} else {
Expand All @@ -444,7 +448,7 @@ std::vector<Action> RbcState::LegalActions() const {
std::string RbcState::ActionToString(Player player, Action action) const {
if (phase_ == MovePhase::kSensing) {
std::string from = chess::SquareToString(
chess::IndexToSquare(action, game()->inner_size()));
chess::IndexToSquare(action, game()->board_size()));
return absl::StrCat("Sense ", from);
} else {
if (action == chess::kPassAction) return "pass";
Expand Down
14 changes: 2 additions & 12 deletions open_spiel/games/rbc.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@
// > three square window centered at the chosen square is revealed to the
// > sensing player."
//
// Sensing is done as picking a sensing window that fully fits within the
// chessboard and is not centered on an underlying square. The centering can
// make the sensing window smaller (as a rectangle near the border of the
// chessboard) which gives strictly less information than a better placed window
// (that remains a full square). This modification eliminates strategically
// useless sensing actions.
// Sensing is done as picking a sensing window that completely or partially fits
// within the chessboard and is centered on an underlying square.
//
// > "If the move was modified [..] then the modified move is made, and
// > the current player is notified of the modified move in the move results."
Expand Down Expand Up @@ -209,7 +205,6 @@ class RbcState : public State {
// How to interpret current actions.
MovePhase phase_;
// Which place was the last sensing made at? (for each player).
// See also RbcGame::inner_size()
std::array<int, 2> sense_location_ = {kSenseLocationNonSpecified,
kSenseLocationNonSpecified};
bool move_captured_ = false;
Expand Down Expand Up @@ -269,11 +264,6 @@ class RbcGame : public Game {

int board_size() const { return board_size_; }
int sense_size() const { return sense_size_; }
// Sensing is done only within the board, as it makes no sense for
// any player to do non-efficient sensing that goes outside of the board.
// The sense location is encoded as coordinates within this smaller
// inner square.
int inner_size() const { return board_size_ - sense_size_ + 1; }

private:
const int board_size_;
Expand Down

0 comments on commit 0e6ff72

Please sign in to comment.