Closed xgshark closed 3 years ago
Hi @xgshark, it's not very basic. :) Yeah that will not work. The cfr_example depends on a lot of the internal code and needs to compile + link with it. This is what the CMake setup helps with: it takes care of all of the dependencies so you don't have to manually.
In our next release, we are intending to include binary-compiled libraries that will let you compile the way you're trying to do now. That's a few months away. But, we already have the target needed to build a binary library for your platform, which I suspect will help compile in the way you're trying to above.
To do that, run this:
BUILD_TYPE=Debug BUILD_SHARED_LIB=ON ./open_spiel/scripts/build_and_run_tests.sh --build_only=true
(Ignore that final error message, this is something I still need to fix on my side)
This will create a build/libopen_spiel.so
which is pure gold, and what we intend to distribute in the next release. Now if you copy the C++ example code below into example_noflags.cc
(absl::flags cannot be included in shared libraries, this is known from the absl team. I still have to look more into this...) and then run the following
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD/build"
cd open_spiel/examples
# g++ might work too but that error you show above required us to move to clang >= 9
# my guess is you'll need clang 9 or clang 10
clang++ -o example_noflags example_noflags.cc -I../ -I../../ -I../abseil-cpp/ -std=c++17 -g -L../../build -lopen_spiel
./example_noflags
Should do it. Here's the contents of the file (it's basically example.cc with the absl::flags removed):
#include <unistd.h>
#include <memory>
#include <random>
#include "open_spiel/abseil-cpp/absl/random/uniform_int_distribution.h"
#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"
void PrintLegalActions(const open_spiel::State& state,
open_spiel::Player player,
const std::vector<open_spiel::Action>& movelist) {
std::cerr << "Legal moves for player " << player << ":" << std::endl;
for (open_spiel::Action action : movelist) {
std::cerr << " " << state.ActionToString(player, action) << std::endl;
}
}
int main(int argc, char** argv) {
//absl::ParseCommandLine(argc, argv);
std::string game_name = "tic_tac_toe";
int players = 0;
bool show_infostate = false;
int seed = 0;
bool show_legals = true;
// Print out registered games.
std::cerr << "Registered games:" << std::endl;
std::vector<std::string> names = open_spiel::RegisteredGames();
for (const std::string& name : names) {
std::cerr << name << std::endl;
}
// Random number generator.
std::mt19937 rng(seed ? seed : time(0));
// Create the game.
std::cerr << "Creating game..\n" << std::endl;
// Add any specified parameters to override the defaults.
open_spiel::GameParameters params;
if (players > 0) {
params["players"] = open_spiel::GameParameter(players);
}
std::shared_ptr<const open_spiel::Game> game =
open_spiel::LoadGame(game_name, params);
if (!game) {
std::cerr << "problem with loading game, exiting..." << std::endl;
return -1;
}
std::cerr << "Starting new game..." << std::endl;
std::unique_ptr<open_spiel::State> state = game->NewInitialState();
std::cerr << "Initial state:" << std::endl;
std::cerr << "State:" << std::endl << state->ToString() << std::endl;
while (!state->IsTerminal()) {
std::cerr << "player " << state->CurrentPlayer() << std::endl;
if (state->IsChanceNode()) {
// Chance node; sample one according to underlying distribution.
std::vector<std::pair<open_spiel::Action, double>> outcomes =
state->ChanceOutcomes();
open_spiel::Action action = open_spiel::SampleAction(outcomes, rng).first;
std::cerr << "sampled outcome: "
<< state->ActionToString(open_spiel::kChancePlayerId, action)
<< std::endl;
state->ApplyAction(action);
} else if (state->IsSimultaneousNode()) {
// open_spiel::Players choose simultaneously?
std::vector<open_spiel::Action> joint_action;
std::vector<float> infostate(game->InformationStateTensorSize());
// Sample a action for each player
for (auto player = open_spiel::Player{0}; player < game->NumPlayers();
++player) {
if (show_infostate) {
if (game->GetType().provides_information_state_tensor) {
state->InformationStateTensor(player, absl::MakeSpan(infostate));
std::cerr << "player " << player << ": "
<< absl::StrJoin(infostate, " ") << std::endl;
}
if (game->GetType().provides_information_state_string) {
std::cerr << "player " << player << ": "
<< state->InformationStateString(player) << std::endl;
}
}
std::vector<open_spiel::Action> actions = state->LegalActions(player);
if (show_legals) {
PrintLegalActions(*state, player, actions);
}
absl::uniform_int_distribution<> dis(0, actions.size() - 1);
open_spiel::Action action = actions[dis(rng)];
joint_action.push_back(action);
std::cerr << "player " << player << " chose "
<< state->ActionToString(player, action) << std::endl;
}
state->ApplyActions(joint_action);
} else {
// Decision node, sample one uniformly.
auto player = state->CurrentPlayer();
if (show_infostate) {
if (game->GetType().provides_information_state_tensor) {
std::vector<float> infostate;
state->InformationStateTensor(player, absl::MakeSpan(infostate));
std::cerr << "player " << player << ": "
<< absl::StrJoin(infostate, " ") << std::endl;
}
if (game->GetType().provides_information_state_string) {
std::cerr << "player " << player << ": "
<< state->InformationStateString(player) << std::endl;
}
}
std::vector<open_spiel::Action> actions = state->LegalActions();
if (show_legals) {
PrintLegalActions(*state, player, actions);
}
absl::uniform_int_distribution<> dis(0, actions.size() - 1);
auto action = actions[dis(rng)];
std::cerr << "chose action: " << state->ActionToString(player, action)
<< std::endl;
state->ApplyAction(action);
}
std::cerr << "State: " << std::endl << state->ToString() << std::endl;
}
auto returns = state->Returns();
for (auto p = open_spiel::Player{0}; p < game->NumPlayers(); p++) {
std::cerr << "Final return to player " << p << " is " << returns[p]
<< std::endl;
}
}
Hope this helps. This will be a lot smoother in a few months.
@xgshark I'm not sure this helps with your original problem but the following vscode (build + debug) setup works for me:
build_and_run_tests.sh
script (it does so in parallel + only builds targets where source files have changed so you don't have to rebuild everything from scratch every time you change something). Just make sure you specify the build directory in your settings file, e.g. I have "cmake.buildDirectory": "${workspaceFolder}/build/${buildType}",
which puts the binaries into build/Debug
and build/Release
(note that you need to create those manually if I recall correctly or at least initiate re-generation of CMake Tools cache). You also need to add "cmake.sourceDirectory": "${workspaceFolder}/open_spiel",
to your settings.type
key changes in that case, take a look at https://code.visualstudio.com/docs/cpp/launch-json-reference for more info)
{
"name": "CFR Example",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/Debug/examples/cfr_example",
"args": [],
"terminal": "console"
}
The above launches the specified program and prints the output in the vscode debug console.
Hope this helps, let me know if you have additional questions.
Works now, thank you Marc and Nejc for your detailed help.
In case somebody has the same issue and follows the instructions step by step: Only extra thing I had to do was to make the libopen_spiel.so discoverable for the system f.e.:
sudo cp build/libopen_spiel.so /usr/local/lib/ && sudo rm /etc/ld.so.cache && sudo ldconfig
Great!
I am trying to open the examples with a vscode debugger under Linux to get a better understanding what is happening in there.
I could only figure out one way to change and build those which is to run open_spiel/scripts/build_and_run_tests.sh again after editing. When I change BUILD_TYPE in CMakeList.txt to Debug I get those symbols supposedly. I do not get vscode to find the correct source file for that executable or something either way the graphical debugger does not work.
I get the debugger to work with a simple 5 line test source file that I edited and compiled myself in the examples directory.
How can I build a source file that uses the open_spiel libraries? I tried this:
g++ cfr_example.cc -I../ -I../../ -I../abseil-cpp/ -std=c++17 -g
I get this: In file included from ../../open_spiel/spiel.h:36, from ../../open_spiel/policy.h:25, from ../../open_spiel/games/universal_poker.h:28, from main.cc:4: ../../open_spiel/game_parameters.h:132:13: error: explicit specialization in non-namespace scope ‘class open_spiel::GameParameter’ 132 | template <> | ^ ../../open_spiel/game_parameters.h:136:13: error: explicit specialization in non-namespace scope ‘class open_spiel::GameParameter’ 136 | template <> ...
Sorry if this is very basic. The code is incredibly well commented and very accessible. I spent two days trying to figure out this building stuff though.